restore/backup tests for events (#995)

## Description

Test restoring a single calendar and multiple calendars of events

Manually compare Location models because they have some fields that are marked as for internal use and appear to be overwritten/controlled by M365

## Type of change

<!--- Please check the type of change your PR introduces: --->
- [ ] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [x] 🤖 Test
- [ ] 💻 CI/Deployment
- [ ] 🐹 Trivial/Minor

## Issue(s)

* #913 

## Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2022-09-30 16:39:33 -07:00 committed by GitHub
parent 526cc8fa9b
commit 88af7f9b7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 489 additions and 131 deletions

View File

@ -50,7 +50,16 @@ func mustToDataLayerPath(
return res
}
func emptyOrEqual[T any](t *testing.T, expected *T, got *T, msg string) {
func emptyOrEqual[T any](expected *T, got *T) bool {
if expected == nil || got == nil {
// Creates either the zero value or gets the value pointed to.
return reflect.DeepEqual(reflect.ValueOf(expected).Elem(), reflect.ValueOf(got).Elem())
}
return reflect.DeepEqual(*expected, *got)
}
func testEmptyOrEqual[T any](t *testing.T, expected *T, got *T, msg string) {
t.Helper()
if expected == nil || got == nil {
@ -90,7 +99,7 @@ func checkMessage(
) {
assert.Equal(t, expected.GetBccRecipients(), got.GetBccRecipients(), "BccRecipients")
emptyOrEqual(t, expected.GetBody().GetContentType(), got.GetBody().GetContentType(), "Body.ContentType")
testEmptyOrEqual(t, expected.GetBody().GetContentType(), got.GetBody().GetContentType(), "Body.ContentType")
// Skip Body.Content as there may be display formatting that changes.
@ -114,44 +123,44 @@ func checkMessage(
assert.Equal(t, expected.GetFrom(), got.GetFrom(), "From")
emptyOrEqual(t, expected.GetHasAttachments(), got.GetHasAttachments(), "HasAttachments")
testEmptyOrEqual(t, expected.GetHasAttachments(), got.GetHasAttachments(), "HasAttachments")
// Skip Id as it's tied to this specific instance of the item.
emptyOrEqual(t, expected.GetImportance(), got.GetImportance(), "Importance")
testEmptyOrEqual(t, expected.GetImportance(), got.GetImportance(), "Importance")
emptyOrEqual(t, expected.GetInferenceClassification(), got.GetInferenceClassification(), "InferenceClassification")
testEmptyOrEqual(t, expected.GetInferenceClassification(), got.GetInferenceClassification(), "InferenceClassification")
assert.Equal(t, expected.GetInternetMessageHeaders(), got.GetInternetMessageHeaders(), "InternetMessageHeaders")
emptyOrEqual(t, expected.GetInternetMessageId(), got.GetInternetMessageId(), "InternetMessageId")
testEmptyOrEqual(t, expected.GetInternetMessageId(), got.GetInternetMessageId(), "InternetMessageId")
emptyOrEqual(
testEmptyOrEqual(
t,
expected.GetIsDeliveryReceiptRequested(),
got.GetIsDeliveryReceiptRequested(),
"IsDeliverReceiptRequested",
)
emptyOrEqual(t, expected.GetIsDraft(), got.GetIsDraft(), "IsDraft")
testEmptyOrEqual(t, expected.GetIsDraft(), got.GetIsDraft(), "IsDraft")
emptyOrEqual(t, expected.GetIsRead(), got.GetIsRead(), "IsRead")
testEmptyOrEqual(t, expected.GetIsRead(), got.GetIsRead(), "IsRead")
emptyOrEqual(t, expected.GetIsReadReceiptRequested(), got.GetIsReadReceiptRequested(), "IsReadReceiptRequested")
testEmptyOrEqual(t, expected.GetIsReadReceiptRequested(), got.GetIsReadReceiptRequested(), "IsReadReceiptRequested")
// Skip LastModifiedDateTime as it's tied to this specific instance of the item.
// Skip ParentFolderId as we restore to a different folder by default.
emptyOrEqual(t, expected.GetReceivedDateTime(), got.GetReceivedDateTime(), "ReceivedDateTime")
testEmptyOrEqual(t, expected.GetReceivedDateTime(), got.GetReceivedDateTime(), "ReceivedDateTime")
assert.Equal(t, expected.GetReplyTo(), got.GetReplyTo(), "ReplyTo")
assert.Equal(t, expected.GetSender(), got.GetSender(), "Sender")
emptyOrEqual(t, expected.GetSentDateTime(), got.GetSentDateTime(), "SentDateTime")
testEmptyOrEqual(t, expected.GetSentDateTime(), got.GetSentDateTime(), "SentDateTime")
emptyOrEqual(t, expected.GetSubject(), got.GetSubject(), "Subject")
testEmptyOrEqual(t, expected.GetSubject(), got.GetSubject(), "Subject")
assert.Equal(t, expected.GetToRecipients(), got.GetToRecipients(), "ToRecipients")
@ -165,13 +174,13 @@ func checkContact(
expected models.Contactable,
got models.Contactable,
) {
emptyOrEqual(t, expected.GetAssistantName(), got.GetAssistantName(), "AssistantName")
testEmptyOrEqual(t, expected.GetAssistantName(), got.GetAssistantName(), "AssistantName")
emptyOrEqual(t, expected.GetBirthday(), got.GetBirthday(), "Birthday")
testEmptyOrEqual(t, expected.GetBirthday(), got.GetBirthday(), "Birthday")
assert.Equal(t, expected.GetBusinessAddress(), got.GetBusinessAddress())
emptyOrEqual(t, expected.GetBusinessHomePage(), got.GetBusinessHomePage(), "BusinessHomePage")
testEmptyOrEqual(t, expected.GetBusinessHomePage(), got.GetBusinessHomePage(), "BusinessHomePage")
assert.Equal(t, expected.GetBusinessPhones(), got.GetBusinessPhones())
@ -181,21 +190,21 @@ func checkContact(
assert.Equal(t, expected.GetChildren(), got.GetChildren())
emptyOrEqual(t, expected.GetCompanyName(), got.GetCompanyName(), "CompanyName")
testEmptyOrEqual(t, expected.GetCompanyName(), got.GetCompanyName(), "CompanyName")
// Skip CreatedDateTime as it's tied to this specific instance of the item.
emptyOrEqual(t, expected.GetDepartment(), got.GetDepartment(), "Department")
testEmptyOrEqual(t, expected.GetDepartment(), got.GetDepartment(), "Department")
emptyOrEqual(t, expected.GetDisplayName(), got.GetDisplayName(), "DisplayName")
testEmptyOrEqual(t, expected.GetDisplayName(), got.GetDisplayName(), "DisplayName")
assert.Equal(t, expected.GetEmailAddresses(), got.GetEmailAddresses())
emptyOrEqual(t, expected.GetFileAs(), got.GetFileAs(), "FileAs")
testEmptyOrEqual(t, expected.GetFileAs(), got.GetFileAs(), "FileAs")
emptyOrEqual(t, expected.GetGeneration(), got.GetGeneration(), "Generation")
testEmptyOrEqual(t, expected.GetGeneration(), got.GetGeneration(), "Generation")
emptyOrEqual(t, expected.GetGivenName(), got.GetGivenName(), "GivenName")
testEmptyOrEqual(t, expected.GetGivenName(), got.GetGivenName(), "GivenName")
assert.Equal(t, expected.GetHomeAddress(), got.GetHomeAddress())
@ -205,43 +214,252 @@ func checkContact(
assert.Equal(t, expected.GetImAddresses(), got.GetImAddresses())
emptyOrEqual(t, expected.GetInitials(), got.GetInitials(), "Initials")
testEmptyOrEqual(t, expected.GetInitials(), got.GetInitials(), "Initials")
emptyOrEqual(t, expected.GetJobTitle(), got.GetJobTitle(), "JobTitle")
testEmptyOrEqual(t, expected.GetJobTitle(), got.GetJobTitle(), "JobTitle")
// Skip CreatedDateTime as it's tied to this specific instance of the item.
emptyOrEqual(t, expected.GetManager(), got.GetManager(), "Manager")
testEmptyOrEqual(t, expected.GetManager(), got.GetManager(), "Manager")
emptyOrEqual(t, expected.GetMiddleName(), got.GetMiddleName(), "MiddleName")
testEmptyOrEqual(t, expected.GetMiddleName(), got.GetMiddleName(), "MiddleName")
emptyOrEqual(t, expected.GetMobilePhone(), got.GetMobilePhone(), "MobilePhone")
testEmptyOrEqual(t, expected.GetMobilePhone(), got.GetMobilePhone(), "MobilePhone")
emptyOrEqual(t, expected.GetNickName(), got.GetNickName(), "NickName")
testEmptyOrEqual(t, expected.GetNickName(), got.GetNickName(), "NickName")
emptyOrEqual(t, expected.GetOfficeLocation(), got.GetOfficeLocation(), "OfficeLocation")
testEmptyOrEqual(t, expected.GetOfficeLocation(), got.GetOfficeLocation(), "OfficeLocation")
assert.Equal(t, expected.GetOtherAddress(), got.GetOtherAddress())
// Skip ParentFolderId as it's tied to this specific instance of the item.
emptyOrEqual(t, expected.GetPersonalNotes(), got.GetPersonalNotes(), "PersonalNotes")
testEmptyOrEqual(t, expected.GetPersonalNotes(), got.GetPersonalNotes(), "PersonalNotes")
assert.Equal(t, expected.GetPhoto(), got.GetPhoto())
emptyOrEqual(t, expected.GetProfession(), got.GetProfession(), "Profession")
testEmptyOrEqual(t, expected.GetProfession(), got.GetProfession(), "Profession")
emptyOrEqual(t, expected.GetSpouseName(), got.GetSpouseName(), "SpouseName")
testEmptyOrEqual(t, expected.GetSpouseName(), got.GetSpouseName(), "SpouseName")
emptyOrEqual(t, expected.GetSurname(), got.GetSurname(), "Surname")
testEmptyOrEqual(t, expected.GetSurname(), got.GetSurname(), "Surname")
emptyOrEqual(t, expected.GetTitle(), got.GetTitle(), "Title")
testEmptyOrEqual(t, expected.GetTitle(), got.GetTitle(), "Title")
emptyOrEqual(t, expected.GetYomiCompanyName(), got.GetYomiCompanyName(), "YomiCompanyName")
testEmptyOrEqual(t, expected.GetYomiCompanyName(), got.GetYomiCompanyName(), "YomiCompanyName")
emptyOrEqual(t, expected.GetYomiGivenName(), got.GetYomiGivenName(), "YomiGivenName")
testEmptyOrEqual(t, expected.GetYomiGivenName(), got.GetYomiGivenName(), "YomiGivenName")
emptyOrEqual(t, expected.GetYomiSurname(), got.GetYomiSurname(), "YomiSurname")
testEmptyOrEqual(t, expected.GetYomiSurname(), got.GetYomiSurname(), "YomiSurname")
}
func checkLocations(
t *testing.T,
expected []models.Locationable,
got []models.Locationable,
) {
pending := make([]*models.Locationable, len(expected))
for i := 0; i < len(expected); i++ {
pending[i] = &expected[i]
}
unexpected := []models.Locationable{}
for i := 0; i < len(got); i++ {
found := false
for j, maybe := range pending {
if maybe == nil {
// Already matched with something in got.
continue
}
// Item matched, break out of inner loop and move to next item in got.
if locationEqual(*maybe, got[i]) {
pending[j] = nil
found = true
break
}
}
if !found {
unexpected = append(unexpected, got[i])
}
}
// Print differences.
missing := []models.Locationable{}
for _, p := range pending {
if p == nil {
continue
}
missing = append(missing, *p)
}
if len(unexpected) == 0 && len(missing) == 0 {
return
}
assert.Failf(
t,
"contain different elements",
"missing items: (%T)%v\nunexpected items: (%T)%v\n",
expected,
missing,
got,
unexpected,
)
}
func locationEqual(expected, got models.Locationable) bool {
if !reflect.DeepEqual(expected.GetAddress(), got.GetAddress()) {
return false
}
if !reflect.DeepEqual(expected.GetCoordinates(), got.GetCoordinates()) {
return false
}
if !emptyOrEqual(expected.GetDisplayName(), got.GetDisplayName()) {
return false
}
if !emptyOrEqual(expected.GetLocationEmailAddress(), got.GetLocationEmailAddress()) {
return false
}
if !emptyOrEqual(expected.GetLocationType(), got.GetLocationType()) {
return false
}
// Skip checking UniqueId as it's marked as for internal use only.
// Skip checking UniqueIdType as it's marked as for internal use only.
if !emptyOrEqual(expected.GetLocationUri(), got.GetLocationUri()) {
return false
}
return true
}
func checkEvent(
t *testing.T,
expected models.Eventable,
got models.Eventable,
) {
testEmptyOrEqual(t, expected.GetAllowNewTimeProposals(), got.GetAllowNewTimeProposals(), "AllowNewTimeProposals")
assert.Equal(t, expected.GetAttachments(), got.GetAttachments(), "Attachments")
assert.Equal(t, expected.GetAttendees(), got.GetAttendees(), "Attendees")
testEmptyOrEqual(t, expected.GetBody().GetContentType(), got.GetBody().GetContentType(), "Body.ContentType")
// Skip checking Body.Content for now as M365 may have different formatting.
// Skip checking BodyPreview for now as M365 may have different formatting.
assert.Equal(t, expected.GetCalendar(), got.GetCalendar(), "Calendar")
assert.Equal(t, expected.GetCategories(), got.GetCategories(), "Categories")
// Skip ChangeKey as it's tied to this specific instance of the item.
// Skip CreatedDateTime as it's tied to this specific instance of the item.
assert.Equal(t, expected.GetEnd(), got.GetEnd(), "End")
testEmptyOrEqual(t, expected.GetHasAttachments(), got.GetHasAttachments(), "HasAttachments")
testEmptyOrEqual(t, expected.GetHideAttendees(), got.GetHideAttendees(), "HideAttendees")
// TODO(ashmrtn): Uncomment when we figure out how to connect to the original
// event.
// testEmptyOrEqual(t, expected.GetICalUId(), got.GetICalUId(), "ICalUId")
// Skip Id as it's tied to this specific instance of the item.
testEmptyOrEqual(t, expected.GetImportance(), got.GetImportance(), "Importance")
assert.Equal(t, expected.GetInstances(), got.GetInstances(), "Instances")
testEmptyOrEqual(t, expected.GetIsAllDay(), got.GetIsAllDay(), "IsAllDay")
testEmptyOrEqual(t, expected.GetIsCancelled(), got.GetIsCancelled(), "IsCancelled")
testEmptyOrEqual(t, expected.GetIsDraft(), got.GetIsDraft(), "IsDraft")
testEmptyOrEqual(t, expected.GetIsOnlineMeeting(), got.GetIsOnlineMeeting(), "IsOnlineMeeting")
// TODO(ashmrtn): Uncomment when we figure out how to delegate event creation
// to another user.
// testEmptyOrEqual(t, expected.GetIsOrganizer(), got.GetIsOrganizer(), "IsOrganizer")
testEmptyOrEqual(t, expected.GetIsReminderOn(), got.GetIsReminderOn(), "IsReminderOn")
// Skip LastModifiedDateTime as it's tied to this specific instance of the item.
// Cheating a little here in the name of code-reuse. model.Location needs
// custom compare logic because it has fields marked as "internal use only"
// that seem to change.
checkLocations(
t,
[]models.Locationable{expected.GetLocation()},
[]models.Locationable{got.GetLocation()},
)
checkLocations(t, expected.GetLocations(), got.GetLocations())
assert.Equal(t, expected.GetOnlineMeeting(), got.GetOnlineMeeting(), "OnlineMeeting")
testEmptyOrEqual(t, expected.GetOnlineMeetingProvider(), got.GetOnlineMeetingProvider(), "OnlineMeetingProvider")
testEmptyOrEqual(t, expected.GetOnlineMeetingUrl(), got.GetOnlineMeetingUrl(), "OnlineMeetingUrl")
// TODO(ashmrtn): Uncomment when we figure out how to delegate event creation
// to another user.
// assert.Equal(t, expected.GetOrganizer(), got.GetOrganizer(), "Organizer")
testEmptyOrEqual(t, expected.GetOriginalEndTimeZone(), got.GetOriginalEndTimeZone(), "OriginalEndTimeZone")
testEmptyOrEqual(t, expected.GetOriginalStart(), got.GetOriginalStart(), "OriginalStart")
testEmptyOrEqual(t, expected.GetOriginalStartTimeZone(), got.GetOriginalStartTimeZone(), "OriginalStartTimeZone")
assert.Equal(t, expected.GetRecurrence(), got.GetRecurrence(), "Recurrence")
testEmptyOrEqual(
t,
expected.GetReminderMinutesBeforeStart(),
got.GetReminderMinutesBeforeStart(),
"ReminderMinutesBeforeStart",
)
testEmptyOrEqual(t, expected.GetResponseRequested(), got.GetResponseRequested(), "ResponseRequested")
// TODO(ashmrtn): Uncomment when we figure out how to connect to the original
// event.
// assert.Equal(t, expected.GetResponseStatus(), got.GetResponseStatus(), "ResponseStatus")
testEmptyOrEqual(t, expected.GetSensitivity(), got.GetSensitivity(), "Sensitivity")
testEmptyOrEqual(t, expected.GetSeriesMasterId(), got.GetSeriesMasterId(), "SeriesMasterId")
testEmptyOrEqual(t, expected.GetShowAs(), got.GetShowAs(), "ShowAs")
assert.Equal(t, expected.GetStart(), got.GetStart(), "Start")
testEmptyOrEqual(t, expected.GetSubject(), got.GetSubject(), "Subject")
testEmptyOrEqual(t, expected.GetTransactionId(), got.GetTransactionId(), "TransactionId")
// Skip LastModifiedDateTime as it's tied to this specific instance of the item.
testEmptyOrEqual(t, expected.GetType(), got.GetType(), "Type")
}
func compareExchangeEmail(
@ -296,6 +514,32 @@ func compareExchangeContact(
checkContact(t, expectedContact, itemContact)
}
func compareExchangeEvent(
t *testing.T,
expected map[string][]byte,
item data.Stream,
) {
itemData, err := io.ReadAll(item.ToReader())
if !assert.NoError(t, err, "reading collection item: %s", item.UUID()) {
return
}
itemEvent, err := support.CreateEventFromBytes(itemData)
if !assert.NoError(t, err, "deserializing backed up contact") {
return
}
expectedBytes, ok := expected[*itemEvent.GetSubject()]
if !assert.True(t, ok, "unexpected item with subject %q", *itemEvent.GetSubject()) {
return
}
expectedEvent, err := support.CreateEventFromBytes(expectedBytes)
assert.NoError(t, err, "deserializing source contact")
checkEvent(t, expectedEvent, itemEvent)
}
func compareItem(
t *testing.T,
expected map[string][]byte,
@ -310,6 +554,8 @@ func compareItem(
compareExchangeEmail(t, expected, item)
case path.ContactsCategory:
compareExchangeContact(t, expected, item)
case path.EventsCategory:
compareExchangeEvent(t, expected, item)
default:
assert.FailNowf(t, "unexpected Exchange category: %s", category.String())
}

View File

@ -569,6 +569,100 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
[]string{dest.ContainerName},
))
return backupSel.Selector
},
},
{
name: "MultipleEventsSingleCalendar",
service: path.ExchangeService,
expectedRestoreFolders: 1,
collections: []colInfo{
{
pathElements: []string{"Work"},
category: path.EventsCategory,
items: []itemInfo{
{
name: "someencodeditemID",
data: mockconnector.GetMockEventWithSubjectBytes("Ghimley"),
lookupKey: "Ghimley",
},
{
name: "someencodeditemID2",
data: mockconnector.GetMockEventWithSubjectBytes("Irgot"),
lookupKey: "Irgot",
},
{
name: "someencodeditemID3",
data: mockconnector.GetMockEventWithSubjectBytes("Jannes"),
lookupKey: "Jannes",
},
},
},
},
// TODO(ashmrtn): Generalize this once we know the path transforms that
// occur during restore.
backupSelFunc: func(dest control.RestoreDestination, backupUser string) selectors.Selector {
backupSel := selectors.NewExchangeBackup()
backupSel.Include(backupSel.EventCalendars(
[]string{backupUser},
[]string{dest.ContainerName},
))
return backupSel.Selector
},
},
{
name: "MultipleEventsMultipleCalendars",
service: path.ExchangeService,
expectedRestoreFolders: 2,
collections: []colInfo{
{
pathElements: []string{"Work"},
category: path.EventsCategory,
items: []itemInfo{
{
name: "someencodeditemID",
data: mockconnector.GetMockEventWithSubjectBytes("Ghimley"),
lookupKey: "Ghimley",
},
{
name: "someencodeditemID2",
data: mockconnector.GetMockEventWithSubjectBytes("Irgot"),
lookupKey: "Irgot",
},
{
name: "someencodeditemID3",
data: mockconnector.GetMockEventWithSubjectBytes("Jannes"),
lookupKey: "Jannes",
},
},
},
{
pathElements: []string{"Personal"},
category: path.EventsCategory,
items: []itemInfo{
{
name: "someencodeditemID4",
data: mockconnector.GetMockEventWithSubjectBytes("Argon"),
lookupKey: "Argon",
},
{
name: "someencodeditemID5",
data: mockconnector.GetMockEventWithSubjectBytes("Bernard"),
lookupKey: "Bernard",
},
},
},
},
// TODO(ashmrtn): Generalize this once we know the path transforms that
// occur during restore.
backupSelFunc: func(dest control.RestoreDestination, backupUser string) selectors.Selector {
backupSel := selectors.NewExchangeBackup()
backupSel.Include(backupSel.EventCalendars(
[]string{backupUser},
[]string{dest.ContainerName},
))
return backupSel.Selector
},
},
@ -619,7 +713,9 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
checkCollections(t, totalItems, expectedData, dcs)
status = backupGC.AwaitStatus()
assert.Equal(t, test.expectedRestoreFolders, status.FolderCount, "status.FolderCount")
// TODO(ashmrtn): This will need to change when the restore layout is
// updated.
assert.Equal(t, 1, status.FolderCount, "status.FolderCount")
assert.Equal(t, totalItems, status.ObjectCount, "status.ObjectCount")
assert.Equal(t, totalItems, status.Successful, "status.Successful")
})

View File

@ -4,13 +4,10 @@ import (
"bytes"
"io"
"math/rand"
"strconv"
"strings"
"time"
"github.com/google/uuid"
"github.com/alcionai/corso/src/internal/common"
"github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/path"
@ -144,96 +141,6 @@ func (med *MockExchangeData) Size() int64 {
return med.size
}
// GetMockContactBytes returns bytes for Contactable item.
// When hydrated: contact.GetGivenName() shows differences
func GetMockContactBytes(middleName string) []byte {
phone := generatePhoneNumber()
//nolint:lll
contact := "{\"id\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAEOAADSEBNbUIB9RL6ePDeF3FIYAABS7DZnAAA=\",\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('foobar%408qzvrj.onmicrosoft.com')/contacts/$entity\"," +
"\"@odata.etag\":\"W/\\\"EQAAABYAAADSEBNbUIB9RL6ePDeF3FIYAABSx4Tr\\\"\",\"categories\":[],\"changeKey\":\"EQAAABYAAADSEBNbUIB9RL6ePDeF3FIYAABSx4Tr\",\"createdDateTime\":\"2019-08-04T06:55:33Z\",\"lastModifiedDateTime\":\"2019-08-04T06:55:33Z\",\"businessAddress\":{},\"businessPhones\":[],\"children\":[]," +
"\"displayName\":\"Santiago Quail\",\"emailAddresses\":[],\"fileAs\":\"Quail, Santiago\",\"mobilePhone\": \"" + phone + "\"," +
"\"givenName\":\"Santiago\",\"homeAddress\":{},\"homePhones\":[],\"imAddresses\":[],\"otherAddress\":{},\"parentFolderId\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9FIYAAAAAAEOAAA=\",\"personalNotes\":\"\",\"middleName\":\"" + middleName + "\",\"surname\":\"Quail\"}"
return []byte(contact)
}
// generatePhoneNumber creates a random phone number
// @return string representation in format (xxx)xxx-xxxx
func generatePhoneNumber() string {
numbers := make([]string, 0)
for i := 0; i < 10; i++ {
temp := rand.Intn(10)
value := strconv.Itoa(temp)
numbers = append(numbers, value)
}
area := strings.Join(numbers[:3], "")
prefix := strings.Join(numbers[3:6], "")
suffix := strings.Join(numbers[6:], "")
phoneNo := "(" + area + ")" + prefix + "-" + suffix
return phoneNo
}
// GetMockEventBytes returns test byte array representative of full Eventable item.
func GetMockEventBytes(subject string) []byte {
newTime := time.Now().AddDate(0, 0, 1)
conversion := common.FormatTime(newTime)
timeSlice := strings.Split(conversion, "T")
//nolint:lll
event := "{\"id\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAAAAAG76AAA=\",\"calendar@odata.navigationLink\":" +
"\"https://graph.microsoft.com/v1.0/users('foobar@8qzvrj.onmicrosoft.com')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')\"," +
"\"calendar@odata.associationLink\":\"https://graph.microsoft.com/v1.0/users('foobar@8qzvrj.onmicrosoft.com')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')/$ref\"," +
"\"@odata.etag\":\"W/\\\"0hATW1CAfUS+njw3hdxSGAAAJIxNug==\\\"\",\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('foobar%408qzvrj.onmicrosoft.com')/events/$entity\",\"categories\":[],\"changeKey\":\"0hATW1CAfUS+njw3hdxSGAAAJIxNug==\"," +
"\"createdDateTime\":\"2022-03-28T03:42:03Z\",\"lastModifiedDateTime\":\"2022-05-26T19:25:58Z\",\"allowNewTimeProposals\":true,\"attendees\"" +
":[],\"body\":{\"content\":\"<html>\\r\\n<head>\\r\\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\">\\r\\n</head>\\r\\n<body>\\r\\n" +
"<p>This meeting is to review the latest Tailspin Toys project proposal.<br>\\r\\nBut why not eat some sushi while were at it? :)</p>\\r\\n</body>\\r\\n</html>\\r\\n\"" +
",\"contentType\":\"html\"},\"bodyPreview\":\"This meeting is to review the latest Tailspin Toys project proposal.\\r\\nBut why not eat some sushi while were at it? :)\"," +
"\"end\":{\"dateTime\":\"" + timeSlice[0] + "T07:00:00.0000000\",\"timeZone\":\"UTC\"},\"hasAttachments\":false,\"hideAttendees\":false,\"iCalUId\":" +
"\"040000008200E00074C5B7101A82E0080000000035723BC75542D801000000000000000010000000E1E7C8F785242E4894DA13AEFB947B85\",\"importance\":\"normal\",\"isAllDay\":false,\"isCancelled\":false," +
"\"isDraft\":false,\"isOnlineMeeting\":false,\"isOrganizer\":false,\"isReminderOn\":true," +
"\"location\":{\"displayName\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\",\"locationType\":\"default\",\"uniqueId\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\"," +
"\"uniqueIdType\":\"private\"},\"locations\":[{\"displayName\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\",\"locationType\":\"default\",\"uniqueId\":\"\",\"uniqueIdType\":\"unknown\"}],\"onlineMeetingProvider\":\"unknown\",\"organizer\"" +
":{\"emailAddress\":{\"address\":\"foobar3@8qzvrj.onmicrosoft.com\",\"name\":\"Anu Pierson\"}},\"originalEndTimeZone\":\"UTC\",\"originalStartTimeZone\":\"UTC\"," +
"\"reminderMinutesBeforeStart\":15,\"responseRequested\":true,\"responseStatus\":{\"response\":\"notResponded\",\"time\":\"0001-01-01T00:00:00Z\"},\"sensitivity\":\"normal\",\"showAs\":\"tentative\"," +
"\"start\":{\"dateTime\":\"" + timeSlice[0] + "T06:00:00.0000000\",\"timeZone\":\"UTC\"}," +
"\"subject\":\" " + subject +
" Review + Lunch\",\"type\":\"singleInstance\",\"webLink\":\"https://outlook.office365.com/owa/?itemid=AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAAAAAG76AAA%3D&exvsurl=1&path=/calendar/item\"}"
return []byte(event)
}
func GetMockEventWithAttendeesBytes(subject string) []byte {
newTime := time.Now().AddDate(0, 0, 1)
conversion := common.FormatTime(newTime)
timeSlice := strings.Split(conversion, "T")
//nolint:lll
event := "{\"id\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAABU_FdvAAA=\",\"@odata.etag\":\"W/\\\"0hATW1CAfUS+njw3hdxSGAAAVK7j9A==\\\"\"," +
"\"calendar@odata.associationLink\":\"https://graph.microsoft.com/v1.0/users('a4a472f8-ccb0-43ec-bf52-3697a91b926c')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')/$ref\"," +
"\"calendar@odata.navigationLink\":\"https://graph.microsoft.com/v1.0/users('a4a472f8-ccb0-43ec-bf52-3697a91b926c')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')\"," +
"\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('a4a472f8-ccb0-43ec-bf52-3697a91b926c')/events/$entity\",\"categories\":[],\"changeKey\":\"0hATW1CAfUS+njw3hdxSGAAAVK7j9A==\",\"createdDateTime\":\"2022-08-06T12:47:56Z\",\"lastModifiedDateTime\":\"2022-08-06T12:49:59Z\",\"allowNewTimeProposals\":true," +
"\"attendees\":[{\"emailAddress\":{\"address\":\"george.martinez@8qzvrj.onmicrosoft.com\",\"name\":\"George Martinez\"},\"type\":\"required\",\"status\":{\"response\":\"none\",\"time\":\"0001-01-01T00:00:00Z\"}},{\"emailAddress\":{\"address\":\"LeeG@8qzvrj.onmicrosoft.com\",\"name\":\"Lee Gu\"},\"type\":\"required\",\"status\":{\"response\":\"none\",\"time\":\"0001-01-01T00:00:00Z\"}}]," +
"\"body\":{\"content\":\"<html>\\n<head>\\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\">\\n</head>\\n<body>\\n<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)\\\">\\nDiscuss matters concerning stock options and early release of quarterly earnings.</div>\\n<br> " +
"\\n<div style=\\\"width:100%; height:20px\\\"><span style=\\\"white-space:nowrap; color:#5F5F5F; opacity:.36\\\">________________________________________________________________________________</span>\\n</div>\\n<div class=\\\"me-email-text\\\" lang=\\\"en-GB\\\" style=\\\"color:#252424; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\"> " +
"\\n<div style=\\\"margin-top:24px; margin-bottom:20px\\\"><span style=\\\"font-size:24px; color:#252424\\\">Microsoft Teams meeting</span>\\n</div>\\n<div style=\\\"margin-bottom:20px\\\">\\n<div style=\\\"margin-top:0px; margin-bottom:0px; font-weight:bold\\\"><span style=\\\"font-size:14px; color:#252424\\\">Join on your computer or mobile app</span>" +
"\\n</div>\\n<a href=\\\"https://teams.microsoft.com/l/meetup-join/19%3ameeting_YWNhMzAxZjItMzE2My00ZGQzLTkzMDUtNjQ3NTY0NjNjMTZi%40thread.v2/0?context=%7b%22Tid%22%3a%224d603060-18d6-4764-b9be-4cb794d32b69%22%2c%22Oid%22%3a%22a4a472f8-ccb0-43ec-bf52-3697a91b926c%22%7d\\\" class=\\\"me-email-headline\\\" style=\\\"font-size:14px; font-family:'Segoe UI Semibold','Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif; text-decoration:underline; color:#6264a7\\\">Click\\n here to join the meeting</a> </div>" +
"\\n<div style=\\\"margin-bottom:20px; margin-top:20px\\\">\\n<div style=\\\"margin-bottom:4px\\\"><span style=\\\"font-size:14px; color:#252424\\\">Meeting ID:\\n<span style=\\\"font-size:16px; color:#252424\\\">292 784 521 247</span> </span><br>\\n<span style=\\\"font-size:14px; color:#252424\\\">Passcode: </span><span style=\\\"font-size:16px; color:#252424\\\">SzBkfK\\n</span>" +
"\\n<div style=\\\"font-size:14px\\\"><a href=\\\"https://www.microsoft.com/en-us/microsoft-teams/download-app\\\" class=\\\"me-email-link\\\" style=\\\"font-size:14px; text-decoration:underline; color:#6264a7; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\">Download\\n Teams</a> | <a href=\\\"https://www.microsoft.com/microsoft-teams/join-a-meeting\\\" class=\\\"me-email-link\\\" style=\\\"font-size:14px; text-decoration:underline; color:#6264a7; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\">" +
"\\nJoin on the web</a></div>\\n</div>\\n</div>\\n<div style=\\\"margin-bottom:24px; margin-top:20px\\\"><a href=\\\"https://aka.ms/JoinTeamsMeeting\\\" class=\\\"me-email-link\\\" style=\\\"font-size:14px; text-decoration:underline; color:#6264a7; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\">Learn more</a>" +
"\\n | <a href=\\\"https://teams.microsoft.com/meetingOptions/?organizerId=a4a472f8-ccb0-43ec-bf52-3697a91b926c&amp;tenantId=4d603060-18d6-4764-b9be-4cb794d32b69&amp;threadId=19_meeting_YWNhMzAxZjItMzE2My00ZGQzLTkzMDUtNjQ3NTY0NjNjMTZi@thread.v2&amp;messageId=0&amp;language=en-GB\\\" class=\\\"me-email-link\\\" style=\\\"font-size:14px; text-decoration:underline; color:#6264a7; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\">" +
"\\nMeeting options</a> </div>\\n</div>\\n<div style=\\\"font-size:14px; margin-bottom:4px; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\">\\n</div>\\n<div style=\\\"font-size:12px\\\"></div>\\n<div></div>\\n<div style=\\\"width:100%; height:20px\\\"><span style=\\\"white-space:nowrap; color:#5F5F5F; opacity:.36\\\">________________________________________________________________________________</span>" +
"\\n</div>\\n</body>\\n</html>\\n\",\"contentType\":\"html\"},\"bodyPreview\":\"Discuss matters concerning stock options and early release of quarterly earnings.\\n\\n\", " +
"\"end\":{\"dateTime\":\"" + timeSlice[0] + "T16:00:00.0000000\",\"timeZone\":\"UTC\"},\"hasAttachments\":false,\"hideAttendees\":false,\"iCalUId\":\"040000008200E00074C5B7101A82E0080000000010A45EC092A9D801000000000000000010000000999C7C6281C2B24A91D5502392B8EF38\",\"importance\":\"normal\",\"isAllDay\":false,\"isCancelled\":false,\"isDraft\":false,\"isOnlineMeeting\":true,\"isOrganizer\":true,\"isReminderOn\":true," +
"\"location\":{\"address\":{},\"coordinates\":{},\"displayName\":\"\",\"locationType\":\"default\",\"uniqueIdType\":\"unknown\"},\"locations\":[],\"onlineMeeting\":{\"joinUrl\":\"https://teams.microsoft.com/l/meetup-join/19%3ameeting_YWNhMzAxZjItMzE2My00ZGQzLTkzMDUtNjQ3NTY0NjNjMTZi%40thread.v2/0?context=%7b%22Tid%22%3a%224d603060-18d6-4764-b9be-4cb794d32b69%22%2c%22Oid%22%3a%22a4a472f8-ccb0-43ec-bf52-3697a91b926c%22%7d\"},\"onlineMeetingProvider\":\"teamsForBusiness\"," +
"\"organizer\":{\"emailAddress\":{\"address\":\"LidiaH@8qzvrj.onmicrosoft.com\",\"name\":\"Lidia Holloway\"}},\"originalEndTimeZone\":\"Eastern Standard Time\",\"originalStartTimeZone\":\"Eastern Standard Time\",\"reminderMinutesBeforeStart\":15,\"responseRequested\":true,\"responseStatus\":{\"response\":\"organizer\",\"time\":\"0001-01-01T00:00:00Z\"},\"sensitivity\":\"normal\",\"showAs\":\"busy\"," +
"\"start\":{\"dateTime\":\"" + timeSlice[0] + "T15:30:00.0000000\",\"timeZone\":\"UTC\"},\"subject\":\"Board " + subject + " Meeting\",\"transactionId\":\"28b36295-6cd3-952f-d8f5-deb313444a51\",\"type\":\"singleInstance\",\"webLink\":\"https://outlook.office365.com/owa/?itemid=AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAABU%2BFdvAAA%3D&exvsurl=1&path=/calendar/item\"}"
return []byte(event)
}
type errReader struct {
readErr error
}

View File

@ -2,6 +2,10 @@ package mockconnector
import (
"fmt"
"math/rand"
"strconv"
"strings"
"time"
"github.com/alcionai/corso/src/internal/common"
)
@ -33,6 +37,28 @@ const (
"\"replyTo\":[],\"sender\":{\"emailAddress\":{\"address\":\"foobar@8qzvrj.onmicrosoft.com\",\"name\":\"A Stranger\"}},\"sentDateTime\":\"2022-09-26T23:15:46Z\"," +
"\"subject\":\"%s\",\"toRecipients\":[{\"emailAddress\":{\"address\":\"LidiaH@8qzvrj.onmicrosoft.com\",\"name\":\"Lidia Holloway\"}}]," +
"\"webLink\":\"https://outlook.office365.com/owa/?ItemID=AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAEMAADSEBNbUIB9RL6ePDeF3FIYAAB3XwIkAAA%%3D&exvsurl=1&viewmodel=ReadMessageItem\"}"
// Order of fields to fill in:
// 1. start/end date
// 2. subject
eventTmpl = "{\"id\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAAAAAG76AAA=\",\"calendar@odata.navigationLink\":" +
"\"https://graph.microsoft.com/v1.0/users('foobar@8qzvrj.onmicrosoft.com')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')\"," +
"\"calendar@odata.associationLink\":\"https://graph.microsoft.com/v1.0/users('foobar@8qzvrj.onmicrosoft.com')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')/$ref\"," +
"\"@odata.etag\":\"W/\\\"0hATW1CAfUS+njw3hdxSGAAAJIxNug==\\\"\",\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('foobar%%408qzvrj.onmicrosoft.com')/events/$entity\",\"categories\":[],\"changeKey\":\"0hATW1CAfUS+njw3hdxSGAAAJIxNug==\"," +
"\"createdDateTime\":\"2022-03-28T03:42:03Z\",\"lastModifiedDateTime\":\"2022-05-26T19:25:58Z\",\"allowNewTimeProposals\":true,\"attendees\"" +
":[],\"body\":{\"content\":\"<html>\\r\\n<head>\\r\\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\">\\r\\n</head>\\r\\n<body>\\r\\n" +
"<p>This meeting is to review the latest Tailspin Toys project proposal.<br>\\r\\nBut why not eat some sushi while were at it? :)</p>\\r\\n</body>\\r\\n</html>\\r\\n\"" +
",\"contentType\":\"html\"},\"bodyPreview\":\"This meeting is to review the latest Tailspin Toys project proposal.\\r\\nBut why not eat some sushi while were at it? :)\"," +
"\"end\":{\"dateTime\":\"%[1]sT07:00:00.0000000\",\"timeZone\":\"UTC\"},\"hasAttachments\":false,\"hideAttendees\":false,\"iCalUId\":" +
"\"040000008200E00074C5B7101A82E0080000000035723BC75542D801000000000000000010000000E1E7C8F785242E4894DA13AEFB947B85\",\"importance\":\"normal\",\"isAllDay\":false,\"isCancelled\":false," +
"\"isDraft\":false,\"isOnlineMeeting\":false,\"isOrganizer\":false,\"isReminderOn\":true," +
"\"location\":{\"displayName\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\",\"locationType\":\"default\",\"uniqueId\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\"," +
"\"uniqueIdType\":\"private\"},\"locations\":[{\"displayName\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\",\"locationType\":\"default\",\"uniqueId\":\"\",\"uniqueIdType\":\"unknown\"}],\"onlineMeetingProvider\":\"unknown\",\"organizer\"" +
":{\"emailAddress\":{\"address\":\"foobar3@8qzvrj.onmicrosoft.com\",\"name\":\"Anu Pierson\"}},\"originalEndTimeZone\":\"UTC\",\"originalStartTimeZone\":\"UTC\"," +
"\"reminderMinutesBeforeStart\":15,\"responseRequested\":true,\"responseStatus\":{\"response\":\"notResponded\",\"time\":\"0001-01-01T00:00:00Z\"},\"sensitivity\":\"normal\",\"showAs\":\"tentative\"," +
"\"start\":{\"dateTime\":\"%[1]sT06:00:00.0000000\",\"timeZone\":\"UTC\"}," +
"\"subject\":\"%s\"," +
"\"type\":\"singleInstance\",\"webLink\":\"https://outlook.office365.com/owa/?itemid=AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAAAAAG76AAA%%3D&exvsurl=1&path=/calendar/item\"}"
)
// GetMockMessageBytes returns bytes for Messageable item.
@ -159,3 +185,86 @@ func GetMessageWithOneDriveAttachment(subject string) []byte {
return []byte(message)
}
// GetMockContactBytes returns bytes for Contactable item.
// When hydrated: contact.GetGivenName() shows differences
func GetMockContactBytes(middleName string) []byte {
phone := generatePhoneNumber()
//nolint:lll
contact := "{\"id\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAEOAADSEBNbUIB9RL6ePDeF3FIYAABS7DZnAAA=\",\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('foobar%408qzvrj.onmicrosoft.com')/contacts/$entity\"," +
"\"@odata.etag\":\"W/\\\"EQAAABYAAADSEBNbUIB9RL6ePDeF3FIYAABSx4Tr\\\"\",\"categories\":[],\"changeKey\":\"EQAAABYAAADSEBNbUIB9RL6ePDeF3FIYAABSx4Tr\",\"createdDateTime\":\"2019-08-04T06:55:33Z\",\"lastModifiedDateTime\":\"2019-08-04T06:55:33Z\",\"businessAddress\":{},\"businessPhones\":[],\"children\":[]," +
"\"displayName\":\"Santiago Quail\",\"emailAddresses\":[],\"fileAs\":\"Quail, Santiago\",\"mobilePhone\": \"" + phone + "\"," +
"\"givenName\":\"Santiago\",\"homeAddress\":{},\"homePhones\":[],\"imAddresses\":[],\"otherAddress\":{},\"parentFolderId\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9FIYAAAAAAEOAAA=\",\"personalNotes\":\"\",\"middleName\":\"" + middleName + "\",\"surname\":\"Quail\"}"
return []byte(contact)
}
// generatePhoneNumber creates a random phone number
// @return string representation in format (xxx)xxx-xxxx
func generatePhoneNumber() string {
numbers := make([]string, 0)
for i := 0; i < 10; i++ {
temp := rand.Intn(10)
value := strconv.Itoa(temp)
numbers = append(numbers, value)
}
area := strings.Join(numbers[:3], "")
prefix := strings.Join(numbers[3:6], "")
suffix := strings.Join(numbers[6:], "")
phoneNo := "(" + area + ")" + prefix + "-" + suffix
return phoneNo
}
// GetMockEventBytes returns test byte array representative of full Eventable item.
func GetMockEventBytes(subject string) []byte {
newTime := time.Now().AddDate(0, 0, 1)
conversion := common.FormatTime(newTime)
timeSlice := strings.Split(conversion, "T")
fullSubject := " " + subject + " Review + Lunch"
formatted := fmt.Sprintf(eventTmpl, timeSlice[0], fullSubject)
return []byte(formatted)
}
func GetMockEventWithSubjectBytes(subject string) []byte {
newTime := time.Now().AddDate(0, 0, 1)
conversion := common.FormatTime(newTime)
timeSlice := strings.Split(conversion, "T")
formatted := fmt.Sprintf(eventTmpl, timeSlice[0], subject)
return []byte(formatted)
}
func GetMockEventWithAttendeesBytes(subject string) []byte {
newTime := time.Now().AddDate(0, 0, 1)
conversion := common.FormatTime(newTime)
timeSlice := strings.Split(conversion, "T")
//nolint:lll
event := "{\"id\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAABU_FdvAAA=\",\"@odata.etag\":\"W/\\\"0hATW1CAfUS+njw3hdxSGAAAVK7j9A==\\\"\"," +
"\"calendar@odata.associationLink\":\"https://graph.microsoft.com/v1.0/users('a4a472f8-ccb0-43ec-bf52-3697a91b926c')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')/$ref\"," +
"\"calendar@odata.navigationLink\":\"https://graph.microsoft.com/v1.0/users('a4a472f8-ccb0-43ec-bf52-3697a91b926c')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')\"," +
"\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('a4a472f8-ccb0-43ec-bf52-3697a91b926c')/events/$entity\",\"categories\":[],\"changeKey\":\"0hATW1CAfUS+njw3hdxSGAAAVK7j9A==\",\"createdDateTime\":\"2022-08-06T12:47:56Z\",\"lastModifiedDateTime\":\"2022-08-06T12:49:59Z\",\"allowNewTimeProposals\":true," +
"\"attendees\":[{\"emailAddress\":{\"address\":\"george.martinez@8qzvrj.onmicrosoft.com\",\"name\":\"George Martinez\"},\"type\":\"required\",\"status\":{\"response\":\"none\",\"time\":\"0001-01-01T00:00:00Z\"}},{\"emailAddress\":{\"address\":\"LeeG@8qzvrj.onmicrosoft.com\",\"name\":\"Lee Gu\"},\"type\":\"required\",\"status\":{\"response\":\"none\",\"time\":\"0001-01-01T00:00:00Z\"}}]," +
"\"body\":{\"content\":\"<html>\\n<head>\\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\">\\n</head>\\n<body>\\n<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)\\\">\\nDiscuss matters concerning stock options and early release of quarterly earnings.</div>\\n<br> " +
"\\n<div style=\\\"width:100%; height:20px\\\"><span style=\\\"white-space:nowrap; color:#5F5F5F; opacity:.36\\\">________________________________________________________________________________</span>\\n</div>\\n<div class=\\\"me-email-text\\\" lang=\\\"en-GB\\\" style=\\\"color:#252424; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\"> " +
"\\n<div style=\\\"margin-top:24px; margin-bottom:20px\\\"><span style=\\\"font-size:24px; color:#252424\\\">Microsoft Teams meeting</span>\\n</div>\\n<div style=\\\"margin-bottom:20px\\\">\\n<div style=\\\"margin-top:0px; margin-bottom:0px; font-weight:bold\\\"><span style=\\\"font-size:14px; color:#252424\\\">Join on your computer or mobile app</span>" +
"\\n</div>\\n<a href=\\\"https://teams.microsoft.com/l/meetup-join/19%3ameeting_YWNhMzAxZjItMzE2My00ZGQzLTkzMDUtNjQ3NTY0NjNjMTZi%40thread.v2/0?context=%7b%22Tid%22%3a%224d603060-18d6-4764-b9be-4cb794d32b69%22%2c%22Oid%22%3a%22a4a472f8-ccb0-43ec-bf52-3697a91b926c%22%7d\\\" class=\\\"me-email-headline\\\" style=\\\"font-size:14px; font-family:'Segoe UI Semibold','Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif; text-decoration:underline; color:#6264a7\\\">Click\\n here to join the meeting</a> </div>" +
"\\n<div style=\\\"margin-bottom:20px; margin-top:20px\\\">\\n<div style=\\\"margin-bottom:4px\\\"><span style=\\\"font-size:14px; color:#252424\\\">Meeting ID:\\n<span style=\\\"font-size:16px; color:#252424\\\">292 784 521 247</span> </span><br>\\n<span style=\\\"font-size:14px; color:#252424\\\">Passcode: </span><span style=\\\"font-size:16px; color:#252424\\\">SzBkfK\\n</span>" +
"\\n<div style=\\\"font-size:14px\\\"><a href=\\\"https://www.microsoft.com/en-us/microsoft-teams/download-app\\\" class=\\\"me-email-link\\\" style=\\\"font-size:14px; text-decoration:underline; color:#6264a7; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\">Download\\n Teams</a> | <a href=\\\"https://www.microsoft.com/microsoft-teams/join-a-meeting\\\" class=\\\"me-email-link\\\" style=\\\"font-size:14px; text-decoration:underline; color:#6264a7; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\">" +
"\\nJoin on the web</a></div>\\n</div>\\n</div>\\n<div style=\\\"margin-bottom:24px; margin-top:20px\\\"><a href=\\\"https://aka.ms/JoinTeamsMeeting\\\" class=\\\"me-email-link\\\" style=\\\"font-size:14px; text-decoration:underline; color:#6264a7; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\">Learn more</a>" +
"\\n | <a href=\\\"https://teams.microsoft.com/meetingOptions/?organizerId=a4a472f8-ccb0-43ec-bf52-3697a91b926c&amp;tenantId=4d603060-18d6-4764-b9be-4cb794d32b69&amp;threadId=19_meeting_YWNhMzAxZjItMzE2My00ZGQzLTkzMDUtNjQ3NTY0NjNjMTZi@thread.v2&amp;messageId=0&amp;language=en-GB\\\" class=\\\"me-email-link\\\" style=\\\"font-size:14px; text-decoration:underline; color:#6264a7; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\">" +
"\\nMeeting options</a> </div>\\n</div>\\n<div style=\\\"font-size:14px; margin-bottom:4px; font-family:'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif\\\">\\n</div>\\n<div style=\\\"font-size:12px\\\"></div>\\n<div></div>\\n<div style=\\\"width:100%; height:20px\\\"><span style=\\\"white-space:nowrap; color:#5F5F5F; opacity:.36\\\">________________________________________________________________________________</span>" +
"\\n</div>\\n</body>\\n</html>\\n\",\"contentType\":\"html\"},\"bodyPreview\":\"Discuss matters concerning stock options and early release of quarterly earnings.\\n\\n\", " +
"\"end\":{\"dateTime\":\"" + timeSlice[0] + "T16:00:00.0000000\",\"timeZone\":\"UTC\"},\"hasAttachments\":false,\"hideAttendees\":false,\"iCalUId\":\"040000008200E00074C5B7101A82E0080000000010A45EC092A9D801000000000000000010000000999C7C6281C2B24A91D5502392B8EF38\",\"importance\":\"normal\",\"isAllDay\":false,\"isCancelled\":false,\"isDraft\":false,\"isOnlineMeeting\":true,\"isOrganizer\":true,\"isReminderOn\":true," +
"\"location\":{\"address\":{},\"coordinates\":{},\"displayName\":\"\",\"locationType\":\"default\",\"uniqueIdType\":\"unknown\"},\"locations\":[],\"onlineMeeting\":{\"joinUrl\":\"https://teams.microsoft.com/l/meetup-join/19%3ameeting_YWNhMzAxZjItMzE2My00ZGQzLTkzMDUtNjQ3NTY0NjNjMTZi%40thread.v2/0?context=%7b%22Tid%22%3a%224d603060-18d6-4764-b9be-4cb794d32b69%22%2c%22Oid%22%3a%22a4a472f8-ccb0-43ec-bf52-3697a91b926c%22%7d\"},\"onlineMeetingProvider\":\"teamsForBusiness\"," +
"\"organizer\":{\"emailAddress\":{\"address\":\"LidiaH@8qzvrj.onmicrosoft.com\",\"name\":\"Lidia Holloway\"}},\"originalEndTimeZone\":\"Eastern Standard Time\",\"originalStartTimeZone\":\"Eastern Standard Time\",\"reminderMinutesBeforeStart\":15,\"responseRequested\":true,\"responseStatus\":{\"response\":\"organizer\",\"time\":\"0001-01-01T00:00:00Z\"},\"sensitivity\":\"normal\",\"showAs\":\"busy\"," +
"\"start\":{\"dateTime\":\"" + timeSlice[0] + "T15:30:00.0000000\",\"timeZone\":\"UTC\"},\"subject\":\"Board " + subject + " Meeting\",\"transactionId\":\"28b36295-6cd3-952f-d8f5-deb313444a51\",\"type\":\"singleInstance\",\"webLink\":\"https://outlook.office365.com/owa/?itemid=AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAABU%2BFdvAAA%3D&exvsurl=1&path=/calendar/item\"}"
return []byte(event)
}