Repository: ctreminiom/go-atlassian
Pull request #190 (2023-04-28 23:22:56)

Feature/notification schemes


Patch:
diff --git a/jira/internal/notification_scheme_impl.go b/jira/internal/notification_scheme_impl.go
new file mode 100644
index 0000000..e162196
--- /dev/null
+++ b/jira/internal/notification_scheme_impl.go
@@ -0,0 +1,320 @@
+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"
+	"net/url"
+	"strconv"
+	"strings"
+)
+
+func NewNotificationSchemeService(client service.Client, version string) (*NotificationSchemeService, error) {
+
+	if version == "" {
+		return nil, model.ErrNoVersionProvided
+	}
+
+	return &NotificationSchemeService{
+		internalClient: &internalNotificationSchemeImpl{c: client, version: version},
+	}, nil
+}
+
+type NotificationSchemeService struct {
+	internalClient jira.NotificationSchemeConnector
+}
+
+// Search returns a paginated list of notification schemes ordered by the display name.
+//
+// GET /rest/api/{2-3}/notificationscheme
+//
+// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#get-notification-schemes
+func (n *NotificationSchemeService) Search(ctx context.Context, options *model.NotificationSchemeSearchOptions, startAt, maxResults int) (*model.NotificationSchemePageScheme, *model.ResponseScheme, error) {
+	return n.internalClient.Search(ctx, options, startAt, maxResults)
+}
+
+// Create creates a notification scheme with notifications. You can create up to 1000 notifications per request.
+//
+// POST /rest/api/{2-3}/notificationscheme
+//
+// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#create-notification-scheme
+func (n *NotificationSchemeService) Create(ctx context.Context, payload *model.NotificationSchemePayloadScheme) (*model.NotificationSchemeCreatedPayload, *model.ResponseScheme, error) {
+	return n.internalClient.Create(ctx, payload)
+}
+
+// Projects returns a paginated mapping of project that have notification scheme assigned.
+//
+// You can provide either one or multiple notification scheme IDs or project IDs to filter by.
+//
+// If you don't provide any, this will return a list of all mappings.
+//
+// Note that only company-managed (classic) projects are supported.
+//
+// This is because team-managed projects don't have a concept of a default notification scheme.
+//
+// The mappings are ordered by projectId.
+//
+// GET /rest/api/{2-3}/notificationscheme/project
+func (n *NotificationSchemeService) Projects(ctx context.Context, schemeIDs, projectIDs []string, startAt, maxResults int) (*model.NotificationSchemeProjectPageScheme, *model.ResponseScheme, error) {
+	return n.internalClient.Projects(ctx, schemeIDs, projectIDs, startAt, maxResults)
+}
+
+// Get returns a notification scheme, including the list of events and the recipients who will
+//
+// receive notifications for those events.
+//
+// GET /rest/api/{2-3}/notificationscheme/{id}
+//
+// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#get-notification-scheme
+func (n *NotificationSchemeService) Get(ctx context.Context, schemeID string, expand []string) (*model.NotificationSchemeScheme, *model.ResponseScheme, error) {
+	return n.internalClient.Get(ctx, schemeID, expand)
+}
+
+// Update updates a notification scheme.
+//
+// PUT /rest/api/{2-3}/notificationscheme/{id}
+//
+// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#update-notification-scheme
+func (n *NotificationSchemeService) Update(ctx context.Context, schemeID string, payload *model.NotificationSchemePayloadScheme) (*model.ResponseScheme, error) {
+	return n.internalClient.Update(ctx, schemeID, payload)
+}
+
+// Append adds notifications to a notification scheme.
+//
+// You can add up to 1000 notifications per request.
+//
+// PUT /rest/api/{2-3}/notificationscheme/{id}/notification
+//
+// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#append-notifications-to-scheme
+func (n *NotificationSchemeService) Append(ctx context.Context, schemeID string, payload *model.NotificationSchemeEventsPayloadScheme) (*model.ResponseScheme, error) {
+	return n.internalClient.Append(ctx, schemeID, payload)
+}
+
+// Delete deletes a notification scheme.
+//
+// DELETE /rest/api/{2-3}/notificationscheme/{notificationSchemeId}
+//
+// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#delete-notification-scheme
+func (n *NotificationSchemeService) Delete(ctx context.Context, schemeID string) (*model.ResponseScheme, error) {
+	return n.internalClient.Delete(ctx, schemeID)
+}
+
+// Remove removes a notification from a notification scheme.
+//
+// DELETE /rest/api/{2-3}/notificationscheme/{notificationSchemeId}/notification/{notificationId}
+//
+// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#remove-notifications-to-scheme
+func (n *NotificationSchemeService) Remove(ctx context.Context, schemeID, notificationID string) (*model.ResponseScheme, error) {
+	return n.internalClient.Remove(ctx, schemeID, notificationID)
+}
+
+type internalNotificationSchemeImpl struct {
+	c       service.Client
+	version string
+}
+
+func (i *internalNotificationSchemeImpl) Search(ctx context.Context, options *model.NotificationSchemeSearchOptions, startAt, maxResults int) (*model.NotificationSchemePageScheme, *model.ResponseScheme, error) {
+
+	params := url.Values{}
+	params.Add("startAt", strconv.Itoa(startAt))
+	params.Add("maxResults", strconv.Itoa(maxResults))
+
+	if options != nil {
+
+		for _, scheme := range options.NotificationSchemeIDs {
+			params.Add("id", scheme)
+		}
+
+		for _, id := range options.ProjectIDs {
+			params.Add("projectId", id)
+		}
+
+		if options.OnlyDefault {
+			params.Add("onlyDefault", "true")
+		}
+
+		if len(options.Expand) != 0 {
+			params.Add("expand", strings.Join(options.Expand, ","))
+		}
+	}
+
+	endpoint := fmt.Sprintf("rest/api/%v/notificationscheme?%v", i.version, params.Encode())
+
+	request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	notificationSchemes := new(model.NotificationSchemePageScheme)
+	response, err := i.c.Call(request, notificationSchemes)
+	if err != nil {
+		return nil, response, err
+	}
+
+	return notificationSchemes, response, nil
+}
+
+func (i *internalNotificationSchemeImpl) Create(ctx context.Context, payload *model.NotificationSchemePayloadScheme) (*model.NotificationSchemeCreatedPayload, *model.ResponseScheme, error) {
+
+	reader, err := i.c.TransformStructToReader(payload)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	endpoint := fmt.Sprintf("rest/api/%v/notificationscheme", i.version)
+
+	request, err := i.c.NewRequest(ctx, http.MethodPost, endpoint, reader)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	notificationScheme := new(model.NotificationSchemeCreatedPayload)
+	response, err := i.c.Call(request, notificationScheme)
+	if err != nil {
+		return nil, response, err
+	}
+
+	return notificationScheme, response, nil
+}
+
+func (i *internalNotificationSchemeImpl) Projects(ctx context.Context, schemeIDs, projectIDs []string, startAt, maxResults int) (*model.NotificationSchemeProjectPageScheme, *model.ResponseScheme, error) {
+
+	params := url.Values{}
+	params.Add("startAt", strconv.Itoa(startAt))
+	params.Add("maxResults", strconv.Itoa(maxResults))
+
+	for _, scheme := range schemeIDs {
+		params.Add("notificationSchemeId", scheme)
+	}
+
+	for _, id := range projectIDs {
+		params.Add("projectId", id)
+	}
+
+	endpoint := fmt.Sprintf("rest/api/%v/notificationscheme/project?%v", i.version, params.Encode())
+
+	request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	notificationProjectSchemes := new(model.NotificationSchemeProjectPageScheme)
+	response, err := i.c.Call(request, notificationProjectSchemes)
+	if err != nil {
+		return nil, response, err
+	}
+
+	return notificationProjectSchemes, response, nil
+}
+
+func (i *internalNotificationSchemeImpl) Get(ctx context.Context, schemeID string, expand []string) (*model.NotificationSchemeScheme, *model.ResponseScheme, error) {
+
+	if schemeID == "" {
+		return nil, nil, model.ErrNoNotificationSchemeIDError
+	}
+
+	var endpoint strings.Builder
+	endpoint.WriteString(fmt.Sprintf("rest/api/%v/notificationscheme/%v", i.version, schemeID))
+
+	if len(expand) != 0 {
+
+		params := url.Values{}
+		params.Add("expand", strings.Join(expand, ","))
+
+		endpoint.WriteString(fmt.Sprintf("?%v", params.Encode()))
+	}
+
+	request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint.String(), nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	notificationScheme := new(model.NotificationSchemeScheme)
+	response, err := i.c.Call(request, notificationScheme)
+	if err != nil {
+		return nil, response, err
+	}
+
+	return notificationScheme, response, nil
+}
+
+func (i *internalNotificationSchemeImpl) Update(ctx context.Context, schemeID string, payload *model.NotificationSchemePayloadScheme) (*model.ResponseScheme, error) {
+
+	if schemeID == "" {
+		return nil, model.ErrNoNotificationSchemeIDError
+	}
+
+	reader, err := i.c.TransformStructToReader(payload)
+	if err != nil {
+		return nil, err
+	}
+
+	endpoint := fmt.Sprintf("rest/api/%v/notificationscheme/%v", i.version, schemeID)
+
+	request, err := i.c.NewRequest(ctx, http.MethodPut, endpoint, reader)
+	if err != nil {
+		return nil, err
+	}
+
+	return i.c.Call(request, nil)
+}
+
+func (i *internalNotificationSchemeImpl) Append(ctx context.Context, schemeID string, payload *model.NotificationSchemeEventsPayloadScheme) (*model.ResponseScheme, error) {
+
+	if schemeID == "" {
+		return nil, model.ErrNoNotificationSchemeIDError
+	}
+
+	reader, err := i.c.TransformStructToReader(payload)
+	if err != nil {
+		return nil, err
+	}
+
+	endpoint := fmt.Sprintf("rest/api/%v/notificationscheme/%v/notification", i.version, schemeID)
+
+	request, err := i.c.NewRequest(ctx, http.MethodPut, endpoint, reader)
+	if err != nil {
+		return nil, err
+	}
+
+	return i.c.Call(request, nil)
+}
+
+func (i *internalNotificationSchemeImpl) Delete(ctx context.Context, schemeID string) (*model.ResponseScheme, error) {
+
+	if schemeID == "" {
+		return nil, model.ErrNoNotificationSchemeIDError
+	}
+
+	endpoint := fmt.Sprintf("rest/api/%v/notificationscheme/%v", i.version, schemeID)
+
+	request, err := i.c.NewRequest(ctx, http.MethodDelete, endpoint, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return i.c.Call(request, nil)
+}
+
+func (i *internalNotificationSchemeImpl) Remove(ctx context.Context, schemeID, notificationID string) (*model.ResponseScheme, error) {
+
+	if schemeID == "" {
+		return nil, model.ErrNoNotificationSchemeIDError
+	}
+
+	if notificationID == "" {
+		return nil, model.ErrNoNotificationIDError
+	}
+
+	endpoint := fmt.Sprintf("rest/api/%v/notificationscheme/%v/notification/%v", i.version, schemeID, notificationID)
+
+	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/v2/api_client_impl.go b/jira/v2/api_client_impl.go
index 8074305..4e9f0f2 100644
--- a/jira/v2/api_client_impl.go
+++ b/jira/v2/api_client_impl.go
@@ -270,6 +270,11 @@ func New(httpClient common.HttpClient, site string) (*Client, error) {
 		return nil, err
 	}
 
+	projectNotificationScheme, err := internal.NewNotificationSchemeService(client, "2")
+	if err != nil {
+		return nil, err
+	}
+
 	projectSubService := &internal.ProjectChildServices{
 		Category:   projectCategory,
 		Component:  projectComponent,
@@ -363,29 +368,31 @@ func New(httpClient common.HttpClient, site string) (*Client, error) {
 	client.User = user
 	client.Workflow = workflow
 	client.JQL = jql
+	client.NotificationScheme = projectNotificationScheme
 
 	return client, nil
 }
 
 type Client struct {
-	HTTP       common.HttpClient
-	Auth       common.Authentication
-	Site       *url.URL
-	Role       *internal.ApplicationRoleService
-	Audit      *internal.AuditRecordService
-	Dashboard  *internal.DashboardService
-	Filter     *internal.FilterService
-	Group      *internal.GroupService
-	Issue      *internal.IssueRichTextService
-	MySelf     *internal.MySelfService
-	Permission *internal.PermissionService
-	Project    *internal.ProjectService
-	Screen     *internal.ScreenService
-	Task       *internal.TaskService
-	Server     *internal.ServerService
-	User       *internal.UserService
-	Workflow   *internal.WorkflowService
-	JQL        *internal.JQLService
+	HTTP               common.HttpClient
+	Auth               common.Authentication
+	Site               *url.URL
+	Role               *internal.ApplicationRoleService
+	Audit              *internal.AuditRecordService
+	Dashboard          *internal.DashboardService
+	Filter             *internal.FilterService
+	Group              *internal.GroupService
+	Issue              *internal.IssueRichTextService
+	MySelf             *internal.MySelfService
+	Permission         *internal.PermissionService
+	Project            *internal.ProjectService
+	Screen             *internal.ScreenService
+	Task               *internal.TaskService
+	Server             *internal.ServerService
+	User               *internal.UserService
+	Workflow           *internal.WorkflowService
+	JQL                *internal.JQLService
+	NotificationScheme *internal.NotificationSchemeService
 }
 
 func (c *Client) NewFormRequest(ctx context.Context, method, apiEndpoint, contentType string, payload io.Reader) (*http.Request, error) {
diff --git a/jira/v3/api_client_impl.go b/jira/v3/api_client_impl.go
index 8f3d10a..e2acf35 100644
--- a/jira/v3/api_client_impl.go
+++ b/jira/v3/api_client_impl.go
@@ -270,6 +270,11 @@ func New(httpClient common.HttpClient, site string) (*Client, error) {
 		return nil, err
 	}
 
+	projectNotificationScheme, err := internal.NewNotificationSchemeService(client, "3")
+	if err != nil {
+		return nil, err
+	}
+
 	projectSubService := &internal.ProjectChildServices{
 		Category:   projectCategory,
 		Component:  projectComponent,
@@ -363,29 +368,31 @@ func New(httpClient common.HttpClient, site string) (*Client, error) {
 	client.User = user
 	client.Workflow = workflow
 	client.JQL = jql
+	client.NotificationScheme = projectNotificationScheme
 
 	return client, nil
 }
 
 type Client struct {
-	HTTP       common.HttpClient
-	Auth       common.Authentication
-	Site       *url.URL
-	Audit      *internal.AuditRecordService
-	Role       *internal.ApplicationRoleService
-	Dashboard  *internal.DashboardService
-	Filter     *internal.FilterService
-	Group      *internal.GroupService
-	Issue      *internal.IssueADFService
-	MySelf     *internal.MySelfService
-	Permission *internal.PermissionService
-	Project    *internal.ProjectService
-	Screen     *internal.ScreenService
-	Task       *internal.TaskService
-	Server     *internal.ServerService
-	User       *internal.UserService
-	Workflow   *internal.WorkflowService
-	JQL        *internal.JQLService
+	HTTP               common.HttpClient
+	Auth               common.Authentication
+	Site               *url.URL
+	Audit              *internal.AuditRecordService
+	Role               *internal.ApplicationRoleService
+	Dashboard          *internal.DashboardService
+	Filter             *internal.FilterService
+	Group              *internal.GroupService
+	Issue              *internal.IssueADFService
+	MySelf             *internal.MySelfService
+	Permission         *internal.PermissionService
+	Project            *internal.ProjectService
+	Screen             *internal.ScreenService
+	Task               *internal.TaskService
+	Server             *internal.ServerService
+	User               *internal.UserService
+	Workflow           *internal.WorkflowService
+	JQL                *internal.JQLService
+	NotificationScheme *internal.NotificationSchemeService
 }
 
 func (c *Client) NewFormRequest(ctx context.Context, method, apiEndpoint, contentType string, payload io.Reader) (*http.Request, error) {
diff --git a/pkg/infra/models/errors.go b/pkg/infra/models/errors.go
index 0c1587a..b145b51 100644
--- a/pkg/infra/models/errors.go
+++ b/pkg/infra/models/errors.go
@@ -52,6 +52,8 @@ var (
 	ErrNoLabelNameError                    = errors.New("confluence: no label name set")
 	ErrNoBoardIDError                      = errors.New("agile: no board id set")
 	ErrNoFilterIDError                     = errors.New("agile: no filter id set")
+	ErrNoNotificationSchemeIDError         = errors.New("jira: no notification scheme id set")
+	ErrNoNotificationIDError               = errors.New("jira: no notification id set")
 	ErrNoEpicIDError                       = errors.New("agile: no epic id set")
 	ErrNoSprintIDError                     = errors.New("agile: no sprint id set")
 	ErrNoApplicationRoleError              = errors.New("jira: no application role key set")
diff --git a/pkg/infra/models/jira_notification_scheme.go b/pkg/infra/models/jira_notification_scheme.go
new file mode 100644
index 0000000..df2910f
--- /dev/null
+++ b/pkg/infra/models/jira_notification_scheme.go
@@ -0,0 +1,57 @@
+package models
+
+type NotificationSchemeSearchOptions struct {
+	NotificationSchemeIDs []string
+	ProjectIDs            []string
+	OnlyDefault           bool
+	Expand                []string
+}
+
+type NotificationSchemePayloadScheme struct {
+	Description string                                  `json:"description,omitempty"`
+	Name        string                                  `json:"name,omitempty"`
+	Events      []*NotificationSchemePayloadEventScheme `json:"notificationSchemeEvents,omitempty"`
+}
+
+type NotificationSchemePayloadEventScheme struct {
+	Event         *NotificationSchemeEventTypeScheme           `json:"event,omitempty"`
+	Notifications []*NotificationSchemeEventNotificationScheme `json:"notifications,omitempty"`
+}
+
+type NotificationSchemeEventTypeScheme struct {
+	ID string `json:"id,omitempty"`
+}
+
+type NotificationSchemeEventNotificationScheme struct {
+	NotificationType string `json:"notificationType,omitempty"`
+	Parameter        string `json:"parameter,omitempty"`
+}
+
+type NotificationSchemePageScheme struct {
+	MaxResults int                         `json:"maxResults,omitempty"`
+	StartAt    int                         `json:"startAt,omitempty"`
+	Total      int                         `json:"total,omitempty"`
+	IsLast     bool                        `json:"isLast,omitempty"`
+	Values     []*NotificationSchemeScheme `json:"values,omitempty"`
+}
+
+type NotificationSchemeCreatedPayload struct {
+	Id string `json:"id"`
+}
+
+type NotificationSchemeProjectPageScheme struct {
+	MaxResults int                                `json:"maxResults,omitempty"`
+	StartAt    int                                `json:"startAt,omitempty"`
+	Total      int                                `json:"total,omitempty"`
+	IsLast     bool                               `json:"isLast,omitempty"`
+	Values     []*NotificationSchemeProjectScheme `json:"values,omitempty"`
+}
+
+type NotificationSchemeProjectScheme struct {
+	NotificationSchemeId string `json:"notificationSchemeId,omitempty"`
+	ProjectId            string `json:"projectId,omitempty"`
+}
+
+type NotificationSchemeEventsPayloadScheme struct {
+	NotificationSchemeEvents []*NotificationSchemePayloadEventScheme `json:"notificationSchemeEvents,omitempty"`
+}
diff --git a/pkg/infra/models/jira_project_notification.go b/pkg/infra/models/jira_project_notification.go
index df70e0d..aa941ac 100644
--- a/pkg/infra/models/jira_project_notification.go
+++ b/pkg/infra/models/jira_project_notification.go
@@ -8,6 +8,7 @@ type NotificationSchemeScheme struct {
 	Description              string                                  `json:"description,omitempty"`
 	NotificationSchemeEvents []*ProjectNotificationSchemeEventScheme `json:"notificationSchemeEvents,omitempty"`
 	Scope                    *TeamManagedProjectScopeScheme          `json:"scope,omitempty"`
+	Projects                 []int                                   `json:"projects,omitempty"`
 }
 
 type ProjectNotificationSchemeEventScheme struct {
diff --git a/service/jira/notification.go b/service/jira/notification.go
new file mode 100644
index 0000000..3a0acd0
--- /dev/null
+++ b/service/jira/notification.go
@@ -0,0 +1,80 @@
+package jira
+
+import (
+	"context"
+	"github.com/ctreminiom/go-atlassian/pkg/infra/models"
+)
+
+// NotificationSchemeConnector represents notification schemes,
+// lists of events and the recipients who will receive notifications for those events.
+// Use it to get details of a notification scheme and a list of notification schemes.
+type NotificationSchemeConnector interface {
+
+	// Search returns a paginated list of notification schemes ordered by the display name.
+	//
+	// GET /rest/api/{2-3}/notificationscheme
+	//
+	// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#get-notification-schemes
+	Search(ctx context.Context, options *models.NotificationSchemeSearchOptions, startAt, maxResults int) (*models.NotificationSchemePageScheme, *models.ResponseScheme, error)
+
+	// Create creates a notification scheme with notifications. You can create up to 1000 notifications per request.
+	//
+	// POST /rest/api/{2-3}/notificationscheme
+	//
+	// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#create-notification-scheme
+	Create(ctx context.Context, payload *models.NotificationSchemePayloadScheme) (*models.NotificationSchemeCreatedPayload, *models.ResponseScheme, error)
+
+	// Projects returns a paginated mapping of project that have notification scheme assigned.
+	//
+	// You can provide either one or multiple notification scheme IDs or project IDs to filter by.
+	//
+	// If you don't provide any, this will return a list of all mappings.
+	//
+	// Note that only company-managed (classic) projects are supported.
+	//
+	// This is because team-managed projects don't have a concept of a default notification scheme.
+	//
+	// The mappings are ordered by projectId.
+	//
+	// GET /rest/api/{2-3}/notificationscheme/project
+	Projects(ctx context.Context, schemeIDs, projectIDs []string, startAt, maxResults int) (*models.NotificationSchemeProjectPageScheme, *models.ResponseScheme, error)
+
+	// Get returns a notification scheme, including the list of events and the recipients who will
+	//
+	// receive notifications for those events.
+	//
+	// GET /rest/api/{2-3}/notificationscheme/{id}
+	//
+	// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#get-notification-scheme
+	Get(ctx context.Context, schemeID string, expand []string) (*models.NotificationSchemeScheme, *models.ResponseScheme, error)
+
+	// Update updates a notification scheme.
+	//
+	// PUT /rest/api/{2-3}/notificationscheme/{id}
+	//
+	// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#update-notification-scheme
+	Update(ctx context.Context, schemeID string, payload *models.NotificationSchemePayloadScheme) (*models.ResponseScheme, error)
+
+	// Append adds notifications to a notification scheme.
+	//
+	// You can add up to 1000 notifications per request.
+	//
+	// PUT /rest/api/{2-3}/notificationscheme/{id}/notification
+	//
+	// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#append-notifications-to-scheme
+	Append(ctx context.Context, schemeID string, payload *models.NotificationSchemeEventsPayloadScheme) (*models.ResponseScheme, error)
+
+	// Delete deletes a notification scheme.
+	//
+	// DELETE /rest/api/{2-3}/notificationscheme/{notificationSchemeId}
+	//
+	// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#delete-notification-scheme
+	Delete(ctx context.Context, schemeID string) (*models.ResponseScheme, error)
+
+	// Remove removes a notification from a notification scheme.
+	//
+	// DELETE /rest/api/{2-3}/notificationscheme/{notificationSchemeId}/notification/{notificationId}
+	//
+	// https://docs.go-atlassian.io/jira-software-cloud/projects/notification-schemes#remove-notifications-to-scheme
+	Remove(ctx context.Context, schemeID, notificationID string) (*models.ResponseScheme, error)
+}


Test patch:
diff --git a/jira/internal/notification_scheme_impl_test.go b/jira/internal/notification_scheme_impl_test.go
new file mode 100644
index 0000000..5af5b24
--- /dev/null
+++ b/jira/internal/notification_scheme_impl_test.go
@@ -0,0 +1,1268 @@
+package internal
+
+import (
+	"bytes"
+	"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_internalNotificationSchemeImpl_Search(t *testing.T) {
+
+	type fields struct {
+		c       service.Client
+		version string
+	}
+
+	type args struct {
+		ctx                 context.Context
+		options             *model.NotificationSchemeSearchOptions
+		startAt, maxResults int
+	}
+
+	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.TODO(),
+				options: &model.NotificationSchemeSearchOptions{
+					NotificationSchemeIDs: []string{"1000", "1001"},
+					ProjectIDs:            []string{"50001", "50002"},
+					OnlyDefault:           true,
+					Expand:                []string{"all"},
+				},
+				startAt:    100,
+				maxResults: 50,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/3/notificationscheme?expand=all&id=1000&id=1001&maxResults=50&onlyDefault=true&projectId=50001&projectId=50002&startAt=100",
+					nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.NotificationSchemePageScheme{}).
+					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.TODO(),
+				options: &model.NotificationSchemeSearchOptions{
+					NotificationSchemeIDs: []string{"1000", "1001"},
+					ProjectIDs:            []string{"50001", "50002"},
+					OnlyDefault:           true,
+					Expand:                []string{"all"},
+				},
+				startAt:    100,
+				maxResults: 50,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/2/notificationscheme?expand=all&id=1000&id=1001&maxResults=50&onlyDefault=true&projectId=50001&projectId=50002&startAt=100",
+					nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.NotificationSchemePageScheme{}).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx: context.TODO(),
+				options: &model.NotificationSchemeSearchOptions{
+					NotificationSchemeIDs: []string{"1000", "1001"},
+					ProjectIDs:            []string{"50001", "50002"},
+					OnlyDefault:           true,
+					Expand:                []string{"all"},
+				},
+				startAt:    100,
+				maxResults: 50,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/3/notificationscheme?expand=all&id=1000&id=1001&maxResults=50&onlyDefault=true&projectId=50001&projectId=50002&startAt=100",
+					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 := NewNotificationSchemeService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResult, gotResponse, err := newService.Search(testCase.args.ctx, testCase.args.options, testCase.args.startAt,
+				testCase.args.maxResults)
+
+			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_internalNotificationSchemeImpl_Projects(t *testing.T) {
+
+	type fields struct {
+		c       service.Client
+		version string
+	}
+
+	type args struct {
+		ctx                   context.Context
+		schemeIDs, projectIDs []string
+		startAt, maxResults   int
+	}
+
+	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.TODO(),
+				schemeIDs:  []string{"scheme-id"},
+				projectIDs: []string{"10001"},
+				startAt:    100,
+				maxResults: 50,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/3/notificationscheme/project?maxResults=50&notificationSchemeId=scheme-id&projectId=10001&startAt=100",
+					nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.NotificationSchemeProjectPageScheme{}).
+					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.TODO(),
+				schemeIDs:  []string{"scheme-id"},
+				projectIDs: []string{"10001"},
+				startAt:    100,
+				maxResults: 50,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/2/notificationscheme/project?maxResults=50&notificationSchemeId=scheme-id&projectId=10001&startAt=100",
+					nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.NotificationSchemeProjectPageScheme{}).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:        context.TODO(),
+				schemeIDs:  []string{"scheme-id"},
+				projectIDs: []string{"10001"},
+				startAt:    100,
+				maxResults: 50,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/3/notificationscheme/project?maxResults=50&notificationSchemeId=scheme-id&projectId=10001&startAt=100",
+					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 := NewNotificationSchemeService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResult, gotResponse, err := newService.Projects(testCase.args.ctx, testCase.args.schemeIDs,
+				testCase.args.projectIDs, testCase.args.startAt,
+				testCase.args.maxResults)
+
+			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_internalNotificationSchemeImpl_Get(t *testing.T) {
+
+	type fields struct {
+		c       service.Client
+		version string
+	}
+
+	type args struct {
+		ctx      context.Context
+		schemeID string
+		expand   []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.TODO(),
+				schemeID: "10001",
+				expand:   []string{"all"},
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/3/notificationscheme/10001?expand=all",
+					nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.NotificationSchemeScheme{}).
+					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.TODO(),
+				schemeID: "10001",
+				expand:   []string{"all"},
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/2/notificationscheme/10001?expand=all",
+					nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.NotificationSchemeScheme{}).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the notification scheme is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx: context.TODO(),
+			},
+			wantErr: true,
+			Err:     model.ErrNoNotificationSchemeIDError,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:      context.TODO(),
+				schemeID: "10001",
+				expand:   []string{"all"},
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/3/notificationscheme/10001?expand=all",
+					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 := NewNotificationSchemeService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResult, gotResponse, err := newService.Get(testCase.args.ctx, testCase.args.schemeID, testCase.args.expand)
+
+			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_internalNotificationSchemeImpl_Update(t *testing.T) {
+
+	payloadMocked := &model.NotificationSchemePayloadScheme{
+		Description: "description update sample",
+		Name:        "new notification scheme name",
+	}
+
+	type fields struct {
+		c       service.Client
+		version string
+	}
+
+	type args struct {
+		ctx      context.Context
+		schemeID string
+		payload  *model.NotificationSchemePayloadScheme
+	}
+
+	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.TODO(),
+				schemeID: "10001",
+				payload:  payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("TransformStructToReader",
+					payloadMocked).
+					Return(bytes.NewReader([]byte{}), nil)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPut,
+					"rest/api/3/notificationscheme/10001",
+					bytes.NewReader([]byte{})).
+					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.TODO(),
+				schemeID: "10001",
+				payload:  payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("TransformStructToReader",
+					payloadMocked).
+					Return(bytes.NewReader([]byte{}), nil)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPut,
+					"rest/api/2/notificationscheme/10001",
+					bytes.NewReader([]byte{})).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					nil).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the notification scheme is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx: context.TODO(),
+			},
+			wantErr: true,
+			Err:     model.ErrNoNotificationSchemeIDError,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:      context.TODO(),
+				schemeID: "10001",
+				payload:  payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("TransformStructToReader",
+					payloadMocked).
+					Return(bytes.NewReader([]byte{}), nil)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPut,
+					"rest/api/3/notificationscheme/10001",
+					bytes.NewReader([]byte{})).
+					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 := NewNotificationSchemeService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResponse, err := newService.Update(testCase.args.ctx, testCase.args.schemeID, 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_internalNotificationSchemeImpl_Append(t *testing.T) {
+
+	payloadMocked := &model.NotificationSchemeEventsPayloadScheme{
+		NotificationSchemeEvents: []*model.NotificationSchemePayloadEventScheme{
+			{
+				Event: &model.NotificationSchemeEventTypeScheme{
+					ID: "1",
+				},
+				Notifications: []*model.NotificationSchemeEventNotificationScheme{
+					{
+						NotificationType: "Group",
+						Parameter:        "jira-administrators",
+					},
+				},
+			},
+		},
+	}
+
+	type fields struct {
+		c       service.Client
+		version string
+	}
+
+	type args struct {
+		ctx      context.Context
+		schemeID string
+		payload  *model.NotificationSchemeEventsPayloadScheme
+	}
+
+	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.TODO(),
+				schemeID: "10001",
+				payload:  payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("TransformStructToReader",
+					payloadMocked).
+					Return(bytes.NewReader([]byte{}), nil)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPut,
+					"rest/api/3/notificationscheme/10001/notification",
+					bytes.NewReader([]byte{})).
+					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.TODO(),
+				schemeID: "10001",
+				payload:  payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("TransformStructToReader",
+					payloadMocked).
+					Return(bytes.NewReader([]byte{}), nil)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPut,
+					"rest/api/2/notificationscheme/10001/notification",
+					bytes.NewReader([]byte{})).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					nil).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the notification scheme is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx: context.TODO(),
+			},
+			wantErr: true,
+			Err:     model.ErrNoNotificationSchemeIDError,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:      context.TODO(),
+				schemeID: "10001",
+				payload:  payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("TransformStructToReader",
+					payloadMocked).
+					Return(bytes.NewReader([]byte{}), nil)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPut,
+					"rest/api/3/notificationscheme/10001/notification",
+					bytes.NewReader([]byte{})).
+					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 := NewNotificationSchemeService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResponse, err := newService.Append(testCase.args.ctx, testCase.args.schemeID, 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_internalNotificationSchemeImpl_Remove(t *testing.T) {
+
+	type fields struct {
+		c       service.Client
+		version string
+	}
+
+	type args struct {
+		ctx            context.Context
+		schemeID       string
+		notificationID 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.TODO(),
+				schemeID:       "10001",
+				notificationID: "10001",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodDelete,
+					"rest/api/3/notificationscheme/10001/notification/10001",
+					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.TODO(),
+				schemeID:       "10001",
+				notificationID: "10001",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodDelete,
+					"rest/api/2/notificationscheme/10001/notification/10001",
+					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 notification scheme is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx: context.TODO(),
+			},
+			wantErr: true,
+			Err:     model.ErrNoNotificationSchemeIDError,
+		},
+
+		{
+			name:   "when the notification id is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:      context.TODO(),
+				schemeID: "10001",
+			},
+			wantErr: true,
+			Err:     model.ErrNoNotificationIDError,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:            context.TODO(),
+				schemeID:       "10001",
+				notificationID: "10001",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodDelete,
+					"rest/api/3/notificationscheme/10001/notification/10001",
+					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 := NewNotificationSchemeService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResponse, err := newService.Remove(testCase.args.ctx, testCase.args.schemeID, testCase.args.notificationID)
+
+			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_internalNotificationSchemeImpl_Delete(t *testing.T) {
+
+	type fields struct {
+		c       service.Client
+		version string
+	}
+
+	type args struct {
+		ctx      context.Context
+		schemeID 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.TODO(),
+				schemeID: "10001",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodDelete,
+					"rest/api/3/notificationscheme/10001",
+					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.TODO(),
+				schemeID: "10001",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodDelete,
+					"rest/api/2/notificationscheme/10001",
+					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 notification scheme is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx: context.TODO(),
+			},
+			wantErr: true,
+			Err:     model.ErrNoNotificationSchemeIDError,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:      context.TODO(),
+				schemeID: "10001",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodDelete,
+					"rest/api/3/notificationscheme/10001",
+					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 := NewNotificationSchemeService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResponse, err := newService.Delete(testCase.args.ctx, testCase.args.schemeID)
+
+			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_internalNotificationSchemeImpl_Create(t *testing.T) {
+
+	payloadMocked := &model.NotificationSchemePayloadScheme{
+		Description: "description update sample",
+		Name:        "new notification scheme name",
+		Events: []*model.NotificationSchemePayloadEventScheme{
+			{
+				Event: &model.NotificationSchemeEventTypeScheme{
+					ID: "1",
+				},
+				Notifications: []*model.NotificationSchemeEventNotificationScheme{
+					{
+						NotificationType: "Group",
+						Parameter:        "jira-administrators",
+					},
+				},
+			},
+		},
+	}
+
+	type fields struct {
+		c       service.Client
+		version string
+	}
+
+	type args struct {
+		ctx     context.Context
+		payload *model.NotificationSchemePayloadScheme
+	}
+
+	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.TODO(),
+				payload: payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("TransformStructToReader",
+					payloadMocked).
+					Return(bytes.NewReader([]byte{}), nil)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPost,
+					"rest/api/3/notificationscheme",
+					bytes.NewReader([]byte{})).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.NotificationSchemeCreatedPayload{}).
+					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.TODO(),
+				payload: payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("TransformStructToReader",
+					payloadMocked).
+					Return(bytes.NewReader([]byte{}), nil)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPost,
+					"rest/api/2/notificationscheme",
+					bytes.NewReader([]byte{})).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.NotificationSchemeCreatedPayload{}).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:     context.TODO(),
+				payload: payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewClient(t)
+
+				client.On("TransformStructToReader",
+					payloadMocked).
+					Return(bytes.NewReader([]byte{}), nil)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPost,
+					"rest/api/3/notificationscheme",
+					bytes.NewReader([]byte{})).
+					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 := NewNotificationSchemeService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResult, gotResponse, err := newService.Create(testCase.args.ctx, 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)
+				assert.NotEqual(t, gotResult, nil)
+			}
+
+		})
+	}
+}