-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #513 from FelixTing/issue-510
feat(notifications): Add Notification DTO and Model
- Loading branch information
Showing
14 changed files
with
452 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// | ||
// Copyright (C) 2021 IOTech Ltd | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package dtos | ||
|
||
import ( | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos/common" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/models" | ||
) | ||
|
||
// Notification and its properties are defined in the APIv2 specification: | ||
// https://app.swaggerhub.com/apis-docs/EdgeXFoundry1/support-notifications/2.x#/Notification | ||
type Notification struct { | ||
common.Versionable `json:",inline"` | ||
Id string `json:"id,omitempty" validate:"omitempty,uuid"` | ||
Created int64 `json:"created,omitempty"` | ||
Modified int64 `json:"modified,omitempty"` | ||
Category string `json:"category,omitempty" validate:"required_without=Labels,omitempty,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"` | ||
Labels []string `json:"labels,omitempty" validate:"required_without=Category,omitempty,gt=0,dive,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"` | ||
Content string `json:"content" validate:"required,edgex-dto-none-empty-string"` | ||
ContentType string `json:"contentType,omitempty"` | ||
Description string `json:"description,omitempty"` | ||
Sender string `json:"sender" validate:"required,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"` | ||
Severity string `json:"severity" validate:"required,oneof='MINOR' 'NORMAL' 'CRITICAL'"` | ||
Status string `json:"status,omitempty" validate:"omitempty,oneof='NEW' 'PROCESSED' 'ESCALATED'"` | ||
} | ||
|
||
// ToNotificationModel transforms the Notification DTO to the Notification Model | ||
func ToNotificationModel(n Notification) models.Notification { | ||
var m models.Notification | ||
m.Id = n.Id | ||
m.Created = n.Created | ||
m.Modified = n.Modified | ||
m.Category = n.Category | ||
m.Labels = n.Labels | ||
m.Content = n.Content | ||
m.ContentType = n.ContentType | ||
m.Description = n.Description | ||
m.Sender = n.Sender | ||
m.Severity = models.NotificationSeverity(n.Severity) | ||
m.Status = models.NotificationStatus(n.Status) | ||
return m | ||
} | ||
|
||
// ToNotificationModels transforms the Notification DTO array to the Notification model array | ||
func ToNotificationModels(notifications []Notification) []models.Notification { | ||
models := make([]models.Notification, len(notifications)) | ||
for i, n := range notifications { | ||
models[i] = ToNotificationModel(n) | ||
} | ||
return models | ||
} | ||
|
||
// FromNotificationModelToDTO transforms the Notification Model to the Notification DTO | ||
func FromNotificationModelToDTO(n models.Notification) Notification { | ||
return Notification{ | ||
Versionable: common.NewVersionable(), | ||
Id: n.Id, | ||
Created: n.Created, | ||
Modified: n.Modified, | ||
Category: string(n.Category), | ||
Labels: n.Labels, | ||
Content: n.Content, | ||
ContentType: n.ContentType, | ||
Description: n.Description, | ||
Sender: n.Sender, | ||
Severity: string(n.Severity), | ||
Status: string(n.Status), | ||
} | ||
} | ||
|
||
// FromNotificationModelsToDTOs transforms the Notification model array to the Notification DTO array | ||
func FromNotificationModelsToDTOs(notifications []models.Notification) []Notification { | ||
dtos := make([]Notification, len(notifications)) | ||
for i, n := range notifications { | ||
dtos[i] = FromNotificationModelToDTO(n) | ||
} | ||
return dtos | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// | ||
// Copyright (C) 2021 IOTech Ltd | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package requests | ||
|
||
import ( | ||
"encoding/json" | ||
|
||
"github.com/edgexfoundry/go-mod-core-contracts/v2/errors" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos/common" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/models" | ||
) | ||
|
||
// AddNotificationRequest defines the Request Content for POST Notification DTO. | ||
// This object and its properties correspond to the AddNotificationRequest object in the APIv2 specification: | ||
// https://app.swaggerhub.com/apis-docs/EdgeXFoundry1/support-notifications/2.x#/AddNotificationRequest | ||
type AddNotificationRequest struct { | ||
common.BaseRequest `json:",inline"` | ||
Notification dtos.Notification `json:"notification"` | ||
} | ||
|
||
// Validate satisfies the Validator interface | ||
func (request AddNotificationRequest) Validate() error { | ||
err := v2.Validate(request) | ||
return err | ||
} | ||
|
||
// UnmarshalJSON implements the Unmarshaler interface for the AddNotificationRequest type | ||
func (request *AddNotificationRequest) UnmarshalJSON(b []byte) error { | ||
var alias struct { | ||
common.BaseRequest | ||
Notification dtos.Notification | ||
} | ||
if err := json.Unmarshal(b, &alias); err != nil { | ||
return errors.NewCommonEdgeX(errors.KindContractInvalid, "Failed to unmarshal request body as JSON.", err) | ||
} | ||
|
||
*request = AddNotificationRequest(alias) | ||
|
||
// validate AddNotificationRequest DTO | ||
if err := request.Validate(); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
// AddNotificationReqToNotificationModels transforms the AddNotificationRequest DTO array to the AddNotificationRequest model array | ||
func AddNotificationReqToNotificationModels(reqs []AddNotificationRequest) (n []models.Notification) { | ||
for _, req := range reqs { | ||
d := dtos.ToNotificationModel(req.Notification) | ||
n = append(n, d) | ||
} | ||
return n | ||
} | ||
|
||
func NewAddNotificationRequest(dto dtos.Notification) AddNotificationRequest { | ||
dto.Versionable = common.NewVersionable() | ||
return AddNotificationRequest{ | ||
BaseRequest: common.NewBaseRequest(), | ||
Notification: dto, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
// | ||
// Copyright (C) 2021 IOTech Ltd | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package requests | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
|
||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos/common" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/models" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
var ( | ||
testNotificationCategory = "category" | ||
testNotificationLabels = []string{"label1", "label2"} | ||
testNotificationContent = "content" | ||
testNotificationContentType = "text/plain" | ||
testNotificationDescription = "description" | ||
testNotificationSender = "sender" | ||
testNotificationSeverity = models.Normal | ||
testNotificationStatus = models.New | ||
) | ||
|
||
var testAddNotification = dtos.Notification{ | ||
Versionable: common.NewVersionable(), | ||
Category: testNotificationCategory, | ||
Labels: testNotificationLabels, | ||
Content: testNotificationContent, | ||
ContentType: testNotificationContentType, | ||
Description: testNotificationDescription, | ||
Sender: testNotificationSender, | ||
Severity: testNotificationSeverity, | ||
Status: testNotificationStatus, | ||
} | ||
|
||
func TestAddNotification_Validate(t *testing.T) { | ||
|
||
noReqId := NewAddNotificationRequest(testAddNotification) | ||
noReqId.RequestId = "" | ||
invalidReqId := NewAddNotificationRequest(testAddNotification) | ||
invalidReqId.RequestId = "abc" | ||
|
||
noCategoryAndLabel := NewAddNotificationRequest(testAddNotification) | ||
noCategoryAndLabel.Notification.Category = "" | ||
noCategoryAndLabel.Notification.Labels = nil | ||
categoryNameWithReservedChar := NewAddNotificationRequest(testAddNotification) | ||
categoryNameWithReservedChar.Notification.Category = namesWithReservedChar[0] | ||
|
||
noContent := NewAddNotificationRequest(testAddNotification) | ||
noContent.Notification.Content = "" | ||
|
||
noSender := NewAddNotificationRequest(testAddNotification) | ||
noSender.Notification.Sender = "" | ||
|
||
noSeverity := NewAddNotificationRequest(testAddNotification) | ||
noSeverity.Notification.Severity = "" | ||
invalidSeverity := NewAddNotificationRequest(testAddNotification) | ||
invalidSeverity.Notification.Severity = "foo" | ||
|
||
invalidStatus := NewAddNotificationRequest(testAddNotification) | ||
invalidStatus.Notification.Status = "foo" | ||
|
||
tests := []struct { | ||
name string | ||
request AddNotificationRequest | ||
expectError bool | ||
}{ | ||
{"valid", NewAddNotificationRequest(testAddNotification), false}, | ||
{"invalid, request ID is not an UUID", invalidReqId, true}, | ||
{"invalid, no category and labels", noCategoryAndLabel, true}, | ||
{"invalid, category name containing reserved chars", categoryNameWithReservedChar, true}, | ||
{"invalid, no content", noContent, true}, | ||
{"invalid, no sender", noSender, true}, | ||
{"invalid, no severity", noSeverity, true}, | ||
{"invalid, unsupported severity level", invalidSeverity, true}, | ||
{"invalid, unsupported status", invalidStatus, true}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
err := tt.request.Validate() | ||
assert.Equal(t, tt.expectError, err != nil, "Unexpected AddNotificationRequest validation result.", err) | ||
}) | ||
} | ||
} | ||
|
||
func TestAddNotification_UnmarshalJSON(t *testing.T) { | ||
addNotificationRequest := NewAddNotificationRequest(testAddNotification) | ||
jsonData, _ := json.Marshal(addNotificationRequest) | ||
tests := []struct { | ||
name string | ||
expected AddNotificationRequest | ||
data []byte | ||
wantErr bool | ||
}{ | ||
{"unmarshal AddNotificationRequest with success", addNotificationRequest, jsonData, false}, | ||
{"unmarshal invalid AddNotificationRequest, empty data", AddNotificationRequest{}, []byte{}, true}, | ||
{"unmarshal invalid AddNotificationRequest, string data", AddNotificationRequest{}, []byte("Invalid AddNotificationRequest"), true}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
var result AddNotificationRequest | ||
err := result.UnmarshalJSON(tt.data) | ||
if tt.wantErr { | ||
require.Error(t, err) | ||
} else { | ||
require.NoError(t, err) | ||
assert.Equal(t, tt.expected, result, "Unmarshal did not result in expected AddNotificationRequest.") | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestAddNotificationReqToNotificationModels(t *testing.T) { | ||
addNotificationRequest := NewAddNotificationRequest(testAddNotification) | ||
requests := []AddNotificationRequest{addNotificationRequest} | ||
expectedNotificationModel := []models.Notification{ | ||
{ | ||
Category: testNotificationCategory, | ||
Content: testNotificationContent, | ||
ContentType: testNotificationContentType, | ||
Description: testNotificationDescription, | ||
Labels: testNotificationLabels, | ||
Sender: testNotificationSender, | ||
Severity: models.NotificationSeverity(testNotificationSeverity), | ||
Status: models.NotificationStatus(testNotificationStatus), | ||
}, | ||
} | ||
resultModels := AddNotificationReqToNotificationModels(requests) | ||
assert.Equal(t, expectedNotificationModel, resultModels, "AddNotificationReqToNotificationModels did not result in expected Notification model.") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.