GC: Restore: SharePoint: Serialization Support (#2224)
## Description Adds serialization method for `SharePoint.Page` objects. Test suite included <!-- Insert PR description--> ## Does this PR need a docs update or release note? - [x] ⛔ No ## Type of change <!--- Please check the type of change your PR introduces: ---> - [x] 🌻 Feature ## Issue(s) <!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. --> * related to #2169<issue> * related to #2173 ## Test Plan - [x] ⚡ Unit test
This commit is contained in:
parent
c7e74edc49
commit
438bcd78ed
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -41,7 +41,7 @@ jobs:
|
||||
working-directory: src
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
|
||||
# single setup and sum cache handling here.
|
||||
# the results will cascade onto both testing and linting.
|
||||
- name: Setup Golang with cache
|
||||
|
||||
@ -202,6 +202,15 @@ func (suite *MockExchangeDataSuite) TestMockByteHydration() {
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "SharePoint: Page",
|
||||
transformation: func(t *testing.T) error {
|
||||
bytes := mockconnector.GetMockPage(subject)
|
||||
_, err := support.CreatePageFromBytes(bytes)
|
||||
|
||||
return err
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
25
src/internal/connector/mockconnector/mock_data_page.go
Normal file
25
src/internal/connector/mockconnector/mock_data_page.go
Normal file
@ -0,0 +1,25 @@
|
||||
package mockconnector
|
||||
|
||||
// GetMockPage returns bytes for models.SitePageable object
|
||||
// Title string changes of fields: name and title
|
||||
func GetMockPage(title string) []byte {
|
||||
fileName := title + ".aspx"
|
||||
|
||||
// Create Test Page
|
||||
//nolint:lll
|
||||
byteArray := []byte("{\"name\":\"" + fileName + "\",\"title\":\"" + title + "\",\"pageLayout\":\"article\",\"showComments\":true," +
|
||||
"\"showRecommendedPages\":false,\"titleArea\":{\"enableGradientEffect\":true,\"imageWebUrl\":\"/_LAYOUTS/IMAGES/VISUALTEMPLATETITLEIMAGE.JPG\"," +
|
||||
"\"layout\":\"colorBlock\",\"showAuthor\":true,\"showPublishedDate\":false,\"showTextBlockAboveTitle\":false,\"textAboveTitle\":\"TEXTABOVETITLE\"," +
|
||||
"\"textAlignment\":\"left\",\"imageSourceType\":2,\"title\":\"sample1\"}," +
|
||||
"\"canvasLayout\":{\"horizontalSections\":[{\"layout\":\"oneThirdRightColumn\",\"id\":\"1\",\"emphasis\":\"none\",\"columns\":[{\"id\":\"1\",\"width\":8," +
|
||||
"\"webparts\":[{\"id\":\"6f9230af-2a98-4952-b205-9ede4f9ef548\",\"innerHtml\":\"<p><b>Hello!</b></p>\"}]},{\"id\":\"2\",\"width\":4," +
|
||||
"\"webparts\":[{\"id\":\"73d07dde-3474-4545-badb-f28ba239e0e1\",\"webPartType\":\"d1d91016-032f-456d-98a4-721247c305e8\",\"data\":{\"dataVersion\":\"1.9\"," +
|
||||
"\"description\":\"Showanimageonyourpage\",\"title\":\"Image\",\"properties\":{\"imageSourceType\":2,\"altText\":\"\",\"overlayText\":\"\"," +
|
||||
"\"siteid\":\"0264cabe-6b92-450a-b162-b0c3d54fe5e8\",\"webid\":\"f3989670-cd37-4514-8ccb-0f7c2cbe5314\",\"listid\":\"bdb41041-eb06-474e-ac29-87093386bb14\"," +
|
||||
"\"uniqueid\":\"d9f94b40-78ba-48d0-a39f-3cb23c2fe7eb\",\"imgWidth\":4288,\"imgHeight\":2848,\"fixAspectRatio\":false,\"captionText\":\"\",\"alignment\":\"Center\"}," +
|
||||
"\"serverProcessedContent\":{\"imageSources\":[{\"key\":\"imageSource\",\"value\":\"/_LAYOUTS/IMAGES/VISUALTEMPLATEIMAGE1.JPG\"}]," +
|
||||
"\"customMetadata\":[{\"key\":\"imageSource\",\"value\":{\"siteid\":\"0264cabe-6b92-450a-b162-b0c3d54fe5e8\",\"webid\":\"f3989670-cd37-4514-8ccb-0f7c2cbe5314\"," +
|
||||
"\"listid\":\"bdb41041-eb06-474e-ac29-87093386bb14\",\"uniqueid\":\"d9f94b40-78ba-48d0-a39f-3cb23c2fe7eb\",\"width\":\"4288\",\"height\":\"2848\"}}]}}}]}]}]}}")
|
||||
|
||||
return byteArray
|
||||
}
|
||||
@ -1,6 +1,9 @@
|
||||
package support
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
bmodels "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models"
|
||||
absser "github.com/microsoft/kiota-abstractions-go/serialization"
|
||||
js "github.com/microsoft/kiota-serialization-json-go"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||
@ -12,7 +15,7 @@ import (
|
||||
func CreateFromBytes(bytes []byte, createFunc absser.ParsableFactory) (absser.Parsable, error) {
|
||||
parseNode, err := js.NewJsonParseNodeFactory().GetRootParseNode("application/json", bytes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parsing byte array into m365 object")
|
||||
return nil, errors.Wrap(err, "deserializing bytes into base m365 object")
|
||||
}
|
||||
|
||||
anObject, err := parseNode.GetObjectValue(createFunc)
|
||||
@ -27,7 +30,7 @@ func CreateFromBytes(bytes []byte, createFunc absser.ParsableFactory) (absser.Pa
|
||||
func CreateMessageFromBytes(bytes []byte) (models.Messageable, error) {
|
||||
aMessage, err := CreateFromBytes(bytes, models.CreateMessageFromDiscriminatorValue)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating m365 exchange.Mail object from provided bytes")
|
||||
return nil, errors.Wrap(err, "deserializing bytes to exchange message")
|
||||
}
|
||||
|
||||
message := aMessage.(models.Messageable)
|
||||
@ -40,7 +43,7 @@ func CreateMessageFromBytes(bytes []byte) (models.Messageable, error) {
|
||||
func CreateContactFromBytes(bytes []byte) (models.Contactable, error) {
|
||||
parsable, err := CreateFromBytes(bytes, models.CreateContactFromDiscriminatorValue)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating m365 exchange.Contact object from provided bytes")
|
||||
return nil, errors.Wrap(err, "deserializing bytes to exchange contact")
|
||||
}
|
||||
|
||||
contact := parsable.(models.Contactable)
|
||||
@ -52,7 +55,7 @@ func CreateContactFromBytes(bytes []byte) (models.Contactable, error) {
|
||||
func CreateEventFromBytes(bytes []byte) (models.Eventable, error) {
|
||||
parsable, err := CreateFromBytes(bytes, models.CreateEventFromDiscriminatorValue)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating m365 exchange.Event object from provided bytes")
|
||||
return nil, errors.Wrap(err, "deserializing bytes to exchange event")
|
||||
}
|
||||
|
||||
event := parsable.(models.Eventable)
|
||||
@ -64,10 +67,33 @@ func CreateEventFromBytes(bytes []byte) (models.Eventable, error) {
|
||||
func CreateListFromBytes(bytes []byte) (models.Listable, error) {
|
||||
parsable, err := CreateFromBytes(bytes, models.CreateListFromDiscriminatorValue)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating m365 sharepoint.List object from provided bytes")
|
||||
return nil, errors.Wrap(err, "deserializing bytes to sharepoint list")
|
||||
}
|
||||
|
||||
list := parsable.(models.Listable)
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// CreatePageFromBytes transforms given bytes in models.SitePageable object
|
||||
func CreatePageFromBytes(bytes []byte) (bmodels.SitePageable, error) {
|
||||
parsable, err := CreateFromBytes(bytes, bmodels.CreateSitePageFromDiscriminatorValue)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "deserializing bytes to sharepoint page")
|
||||
}
|
||||
|
||||
page := parsable.(bmodels.SitePageable)
|
||||
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func HasAttachments(body models.ItemBodyable) bool {
|
||||
if body.GetContent() == nil || body.GetContentType() == nil ||
|
||||
*body.GetContentType() == models.TEXT_BODYTYPE || len(*body.GetContent()) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
content := *body.GetContent()
|
||||
|
||||
return strings.Contains(content, "src=\"cid:")
|
||||
}
|
||||
|
||||
@ -3,10 +3,13 @@ package support
|
||||
import (
|
||||
"testing"
|
||||
|
||||
kioser "github.com/microsoft/kiota-serialization-json-go"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
bmodels "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models"
|
||||
"github.com/alcionai/corso/src/internal/connector/mockconnector"
|
||||
)
|
||||
|
||||
@ -18,6 +21,11 @@ func TestDataSupportSuite(t *testing.T) {
|
||||
suite.Run(t, new(DataSupportSuite))
|
||||
}
|
||||
|
||||
var (
|
||||
empty = "Empty Bytes"
|
||||
invalid = "Invalid Bytes"
|
||||
)
|
||||
|
||||
// TestCreateMessageFromBytes verifies approved mockdata bytes can
|
||||
// be successfully transformed into M365 Message data.
|
||||
func (suite *DataSupportSuite) TestCreateMessageFromBytes() {
|
||||
@ -59,13 +67,13 @@ func (suite *DataSupportSuite) TestCreateContactFromBytes() {
|
||||
isNil assert.ValueAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "Empty Bytes",
|
||||
name: empty,
|
||||
byteArray: make([]byte, 0),
|
||||
checkError: assert.Error,
|
||||
isNil: assert.Nil,
|
||||
},
|
||||
{
|
||||
name: "Invalid Bytes",
|
||||
name: invalid,
|
||||
byteArray: []byte("A random sentence doesn't make an object"),
|
||||
checkError: assert.Error,
|
||||
isNil: assert.Nil,
|
||||
@ -94,13 +102,13 @@ func (suite *DataSupportSuite) TestCreateEventFromBytes() {
|
||||
isNil assert.ValueAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "Empty Byes",
|
||||
name: empty,
|
||||
byteArray: make([]byte, 0),
|
||||
checkError: assert.Error,
|
||||
isNil: assert.Nil,
|
||||
},
|
||||
{
|
||||
name: "Invalid Bytes",
|
||||
name: invalid,
|
||||
byteArray: []byte("Invalid byte stream \"subject:\" Not going to work"),
|
||||
checkError: assert.Error,
|
||||
isNil: assert.Nil,
|
||||
@ -132,13 +140,13 @@ func (suite *DataSupportSuite) TestCreateListFromBytes() {
|
||||
isNil assert.ValueAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "Empty Byes",
|
||||
name: empty,
|
||||
byteArray: make([]byte, 0),
|
||||
checkError: assert.Error,
|
||||
isNil: assert.Nil,
|
||||
},
|
||||
{
|
||||
name: "Invalid Bytes",
|
||||
name: invalid,
|
||||
byteArray: []byte("Invalid byte stream \"subject:\" Not going to work"),
|
||||
checkError: assert.Error,
|
||||
isNil: assert.Nil,
|
||||
@ -159,3 +167,111 @@ func (suite *DataSupportSuite) TestCreateListFromBytes() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *DataSupportSuite) TestCreatePageFromBytes() {
|
||||
tests := []struct {
|
||||
name string
|
||||
checkError assert.ErrorAssertionFunc
|
||||
isNil assert.ValueAssertionFunc
|
||||
getBytes func(t *testing.T) []byte
|
||||
}{
|
||||
{
|
||||
empty,
|
||||
assert.Error,
|
||||
assert.Nil,
|
||||
func(t *testing.T) []byte {
|
||||
return make([]byte, 0)
|
||||
},
|
||||
},
|
||||
{
|
||||
invalid,
|
||||
assert.Error,
|
||||
assert.Nil,
|
||||
func(t *testing.T) []byte {
|
||||
return []byte("snarf")
|
||||
},
|
||||
},
|
||||
{
|
||||
"Valid Page",
|
||||
assert.NoError,
|
||||
assert.NotNil,
|
||||
func(t *testing.T) []byte {
|
||||
pg := bmodels.NewSitePage()
|
||||
title := "Tested"
|
||||
pg.SetTitle(&title)
|
||||
pg.SetName(&title)
|
||||
pg.SetWebUrl(&title)
|
||||
|
||||
writer := kioser.NewJsonSerializationWriter()
|
||||
err := pg.Serialize(writer)
|
||||
require.NoError(t, err)
|
||||
|
||||
byteArray, err := writer.GetSerializedContent()
|
||||
require.NoError(t, err)
|
||||
|
||||
return byteArray
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
result, err := CreatePageFromBytes(test.getBytes(t))
|
||||
test.checkError(t, err)
|
||||
test.isNil(t, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *DataSupportSuite) TestHasAttachments() {
|
||||
tests := []struct {
|
||||
name string
|
||||
hasAttachment assert.BoolAssertionFunc
|
||||
getBodyable func(t *testing.T) models.ItemBodyable
|
||||
}{
|
||||
{
|
||||
name: "Mock w/out attachment",
|
||||
hasAttachment: assert.False,
|
||||
getBodyable: func(t *testing.T) models.ItemBodyable {
|
||||
byteArray := mockconnector.GetMockMessageWithBodyBytes(
|
||||
"Test",
|
||||
"This is testing",
|
||||
"This is testing",
|
||||
)
|
||||
message, err := CreateMessageFromBytes(byteArray)
|
||||
require.NoError(t, err)
|
||||
return message.GetBody()
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Mock w/ inline attachment",
|
||||
hasAttachment: assert.True,
|
||||
getBodyable: func(t *testing.T) models.ItemBodyable {
|
||||
byteArray := mockconnector.GetMessageWithOneDriveAttachment("Test legacy")
|
||||
message, err := CreateMessageFromBytes(byteArray)
|
||||
require.NoError(t, err)
|
||||
return message.GetBody()
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Edge Case",
|
||||
hasAttachment: assert.True,
|
||||
getBodyable: func(t *testing.T) models.ItemBodyable {
|
||||
//nolint:lll
|
||||
content := "<html><head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><style type=\"text/css\" style=\"display:none\">\r\n<!--\r\np\r\n\t{margin-top:0;\r\n\tmargin-bottom:0}\r\n-->\r\n</style></head><body dir=\"ltr\"><div class=\"elementToProof\" style=\"font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)\">Happy New Year,</div><div class=\"elementToProof\" style=\"font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)\"><br></div><div class=\"elementToProof\" style=\"font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)\">In accordance with TPS report guidelines, there have been questions about how to address our activities SharePoint Cover page. Do you believe this is the best picture? </div><div class=\"elementToProof\" style=\"font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)\"><br></div><div class=\"elementToProof\" style=\"font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)\"><img class=\"FluidPluginCopy ContentPasted0 w-2070 h-1380\" size=\"5854817\" data-outlook-trace=\"F:1|T:1\" src=\"cid:85f4faa3-9851-40c7-ba0a-e63dce1185f9\" style=\"max-width:100%\"><br></div><div class=\"elementToProof\" style=\"font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)\"><br></div><div class=\"elementToProof\" style=\"font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)\">Let me know if this meets our culture requirements.</div><div class=\"elementToProof\" style=\"font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)\"><br></div><div class=\"elementToProof\" style=\"font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)\">Warm Regards,</div><div class=\"elementToProof\" style=\"font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)\"><br></div><div class=\"elementToProof\" style=\"font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)\">Dustin</div></body></html>"
|
||||
body := models.NewItemBody()
|
||||
body.SetContent(&content)
|
||||
cat := models.HTML_BODYTYPE
|
||||
body.SetContentType(&cat)
|
||||
return body
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
found := HasAttachments(test.getBodyable(t))
|
||||
test.hasAttachment(t, found)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user