add channel and messages enumerators (#4135)

adds enumerators for channels, and a delta
of channel messages.
Also updates the its struct to include group ids, and reformats some of the struct schema.

---

#### Does this PR need a docs update or release note?

- [x]  No

#### Type of change

- [x] 🌻 Feature

#### Issue(s)

* #3989

#### Test Plan

- [x]  Unit test
- [x] 💚 E2E
This commit is contained in:
Keepers 2023-08-30 11:21:53 -06:00 committed by GitHub
parent b610a602d2
commit 4c452bcd8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 329 additions and 134 deletions

View File

@ -243,7 +243,7 @@ func populateCollections(
func collectItems( func collectItems(
ctx context.Context, ctx context.Context,
pager api.ChannelMessageDeltaEnumerator, pager api.DeltaPager[models.ChatMessageable],
) ([]models.ChatMessageable, error) { ) ([]models.ChatMessageable, error) {
items := []models.ChatMessageable{} items := []models.ChatMessageable{}

View File

@ -16,7 +16,7 @@ type BackupHandler interface {
) (models.Channelable, error) ) (models.Channelable, error)
NewChannelsPager( NewChannelsPager(
teamID string, teamID string,
) api.ChannelDeltaEnumerator ) api.Pager[models.Channelable]
GetMessageByID( GetMessageByID(
ctx context.Context, ctx context.Context,
@ -24,7 +24,7 @@ type BackupHandler interface {
) (models.ChatMessageable, error) ) (models.ChatMessageable, error)
NewMessagePager( NewMessagePager(
teamID, channelID string, teamID, channelID string,
) api.ChannelMessageDeltaEnumerator ) api.DeltaPager[models.ChatMessageable]
GetMessageReplies( GetMessageReplies(
ctx context.Context, ctx context.Context,
@ -34,7 +34,7 @@ type BackupHandler interface {
type BackupMessagesHandler interface { type BackupMessagesHandler interface {
GetMessage(ctx context.Context, teamID, channelID, itemID string) (models.ChatMessageable, error) GetMessage(ctx context.Context, teamID, channelID, itemID string) (models.ChatMessageable, error)
NewMessagePager(teamID, channelID string) api.ChannelMessageDeltaEnumerator NewMessagePager(teamID, channelID string) api.DeltaPager[models.ChatMessageable]
GetChannel(ctx context.Context, teamID, channelID string) (models.Channelable, error) GetChannel(ctx context.Context, teamID, channelID string) (models.Channelable, error)
GetReply(ctx context.Context, teamID, channelID, messageID string) (serialization.Parsable, error) GetReply(ctx context.Context, teamID, channelID, messageID string) (serialization.Parsable, error)
} }

View File

@ -1,43 +1,224 @@
package api package api
import ( import (
"context"
"github.com/microsoftgraph/msgraph-sdk-go/models" "github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/microsoftgraph/msgraph-sdk-go/teams"
"github.com/alcionai/corso/src/internal/common/ptr"
"github.com/alcionai/corso/src/internal/m365/graph"
"github.com/alcionai/corso/src/pkg/logger"
) )
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// item pager // channel message pager
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
type ChannelMessageDeltaEnumerator interface { var _ DeltaPager[models.ChatMessageable] = &channelMessageDeltaPageCtrl{}
DeltaGetPager
ValuesInPageLinker[models.ChatMessageable] type channelMessageDeltaPageCtrl struct {
SetNextLinker resourceID, channelID string
gs graph.Servicer
builder *teams.ItemChannelsItemMessagesDeltaRequestBuilder
options *teams.ItemChannelsItemMessagesDeltaRequestBuilderGetRequestConfiguration
} }
// TODO: implement func (p *channelMessageDeltaPageCtrl) SetNext(nextLink string) {
// var _ ChannelMessageDeltaEnumerator = &messagePageCtrl{} p.builder = teams.NewItemChannelsItemMessagesDeltaRequestBuilder(nextLink, p.gs.Adapter())
}
// type messagePageCtrl struct { func (p *channelMessageDeltaPageCtrl) GetPage(
// gs graph.Servicer ctx context.Context,
// builder *teams.ItemChannelsItemMessagesRequestBuilder ) (DeltaPageLinker, error) {
// options *teams.ItemChannelsItemMessagesRequestBuilderGetRequestConfiguration resp, err := p.builder.Get(ctx, p.options)
// } return resp, graph.Stack(ctx, err).OrNil()
}
func (p *channelMessageDeltaPageCtrl) Reset(context.Context) {
p.builder = p.gs.
Client().
Teams().
ByTeamId(p.resourceID).
Channels().
ByChannelId(p.channelID).
Messages().
Delta()
}
func (p *channelMessageDeltaPageCtrl) ValuesIn(l PageLinker) ([]models.ChatMessageable, error) {
return getValues[models.ChatMessageable](l)
}
func (c Channels) NewChannelMessageDeltaPager(
teamID, channelID, prevDelta string,
) *channelMessageDeltaPageCtrl {
builder := c.Stable.
Client().
Teams().
ByTeamId(teamID).
Channels().
ByChannelId(channelID).
Messages().
Delta()
if len(prevDelta) > 0 {
builder = teams.NewItemChannelsItemMessagesDeltaRequestBuilder(prevDelta, c.Stable.Adapter())
}
options := &teams.ItemChannelsItemMessagesDeltaRequestBuilderGetRequestConfiguration{
Headers: newPreferHeaders(preferPageSize(maxNonDeltaPageSize)),
}
return &channelMessageDeltaPageCtrl{
resourceID: teamID,
channelID: channelID,
builder: builder,
gs: c.Stable,
options: options,
}
}
// GetChannelMessagesDelta fetches a delta of all messages in the channel.
func (c Channels) GetChannelMessagesDelta(
ctx context.Context,
teamID, channelID, prevDelta string,
) ([]models.ChatMessageable, DeltaUpdate, error) {
var (
vs = []models.ChatMessageable{}
pager = c.NewChannelMessageDeltaPager(teamID, channelID, prevDelta)
invalidPrevDelta = len(prevDelta) == 0
newDeltaLink string
)
// Loop through all pages returned by Graph API.
for {
page, err := pager.GetPage(graph.ConsumeNTokens(ctx, graph.SingleGetOrDeltaLC))
if graph.IsErrInvalidDelta(err) {
logger.Ctx(ctx).Infow("Invalid previous delta", "delta_link", prevDelta)
invalidPrevDelta = true
vs = []models.ChatMessageable{}
pager.Reset(ctx)
continue
}
if err != nil {
return nil, DeltaUpdate{}, graph.Wrap(ctx, err, "retrieving page of channel messages")
}
vals, err := pager.ValuesIn(page)
if err != nil {
return nil, DeltaUpdate{}, graph.Wrap(ctx, err, "extracting channel messages from response")
}
vs = append(vs, vals...)
nextLink, deltaLink := NextAndDeltaLink(page)
if len(deltaLink) > 0 {
newDeltaLink = deltaLink
}
if len(nextLink) == 0 {
break
}
pager.SetNext(nextLink)
}
logger.Ctx(ctx).Debugf("retrieved %d channel messages", len(vs))
du := DeltaUpdate{
URL: newDeltaLink,
Reset: invalidPrevDelta,
}
return vs, du, nil
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// channel pager // channel pager
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
type ChannelDeltaEnumerator interface { var _ Pager[models.Channelable] = &channelPageCtrl{}
DeltaGetPager
ValuesInPageLinker[models.Channelable] type channelPageCtrl struct {
SetNextLinker gs graph.Servicer
builder *teams.ItemChannelsRequestBuilder
options *teams.ItemChannelsRequestBuilderGetRequestConfiguration
} }
// TODO: implement func (p *channelPageCtrl) SetNext(nextLink string) {
// var _ ChannelDeltaEnumerator = &channelsPageCtrl{} p.builder = teams.NewItemChannelsRequestBuilder(nextLink, p.gs.Adapter())
}
// type channelsPageCtrl struct { func (p *channelPageCtrl) GetPage(
// gs graph.Servicer ctx context.Context,
// builder *teams.ItemChannelsChannelItemRequestBuilder ) (PageLinker, error) {
// options *teams.ItemChannelsChannelItemRequestBuilderGetRequestConfiguration resp, err := p.builder.Get(ctx, p.options)
// } return resp, graph.Stack(ctx, err).OrNil()
}
func (p *channelPageCtrl) ValuesIn(l PageLinker) ([]models.Channelable, error) {
return getValues[models.Channelable](l)
}
func (c Channels) NewChannelPager(
teamID string,
) *channelPageCtrl {
requestConfig := &teams.ItemChannelsRequestBuilderGetRequestConfiguration{
Headers: newPreferHeaders(preferPageSize(maxNonDeltaPageSize)),
}
res := &channelPageCtrl{
gs: c.Stable,
options: requestConfig,
builder: c.Stable.
Client().
Teams().
ByTeamId(teamID).
Channels(),
}
return res
}
// GetChannels fetches all channels in the team.
func (c Channels) GetChannels(
ctx context.Context,
teamID string,
) ([]models.Channelable, error) {
var (
vs = []models.Channelable{}
pager = c.NewChannelPager(teamID)
)
// Loop through all pages returned by Graph API.
for {
page, err := pager.GetPage(ctx)
if err != nil {
return nil, graph.Wrap(ctx, err, "retrieving page of channels")
}
vals, err := pager.ValuesIn(page)
if err != nil {
return nil, graph.Wrap(ctx, err, "extracting channels from response")
}
vs = append(vs, vals...)
nextLink := ptr.Val(page.GetOdataNextLink())
if len(nextLink) == 0 {
break
}
pager.SetNext(nextLink)
}
logger.Ctx(ctx).Debugf("retrieved %d channels", len(vs))
return vs, nil
}

View File

@ -4,64 +4,70 @@ import (
"testing" "testing"
"github.com/alcionai/clues" "github.com/alcionai/clues"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"github.com/alcionai/corso/src/internal/common/ptr"
"github.com/alcionai/corso/src/internal/tester" "github.com/alcionai/corso/src/internal/tester"
"github.com/alcionai/corso/src/internal/tester/tconfig" "github.com/alcionai/corso/src/internal/tester/tconfig"
) )
type ChannelPagerIntgSuite struct { type ChannelsPagerIntgSuite struct {
tester.Suite tester.Suite
its intgTesterSetup its intgTesterSetup
} }
func TestChannelPagerIntgSuite(t *testing.T) { func TestChannelPagerIntgSuite(t *testing.T) {
suite.Run(t, &ChannelPagerIntgSuite{ suite.Run(t, &ChannelsPagerIntgSuite{
Suite: tester.NewIntegrationSuite( Suite: tester.NewIntegrationSuite(
t, t,
[][]string{tconfig.M365AcctCredEnvs}), [][]string{tconfig.M365AcctCredEnvs}),
}) })
} }
func (suite *ChannelPagerIntgSuite) SetupSuite() { func (suite *ChannelsPagerIntgSuite) SetupSuite() {
suite.its = newIntegrationTesterSetup(suite.T()) suite.its = newIntegrationTesterSetup(suite.T())
} }
// This will be added once 'pager' is implemented func (suite *ChannelsPagerIntgSuite) TestEnumerateChannels() {
// func (suite *ChannelPagerIntgSuite) TestChannels_GetPage() {
// t := suite.T()
// ctx, flush := tester.NewContext(t)
// defer flush()
// teamID := tconfig.M365TeamID(t)
// channelID := tconfig.M365ChannelID(t)
// pager := suite.its.ac.Channels().NewMessagePager(teamID, channelID, []string{})
// a, err := pager.GetPage(ctx)
// assert.NoError(t, err, clues.ToCore(err))
// assert.NotNil(t, a)
// }
func (suite *ChannelPagerIntgSuite) TestChannels_Get() {
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
var ( var (
containerName = "General" t = suite.T()
teamID = tconfig.M365TeamID(t) ac = suite.its.ac.Channels()
chanClient = suite.its.ac.Channels()
) )
// GET channel -should be found ctx, flush := tester.NewContext(t)
channel, err := chanClient.GetChannelByName(ctx, teamID, containerName) defer flush()
assert.NoError(t, err, clues.ToCore(err))
assert.Equal(t, ptr.Val(channel.GetDisplayName()), containerName)
// GET channel -should be found chans, err := ac.GetChannels(ctx, suite.its.group.id)
_, err = chanClient.GetChannel(ctx, teamID, ptr.Val(channel.GetId())) require.NoError(t, err, clues.ToCore(err))
assert.NoError(t, err, clues.ToCore(err)) require.NotEmpty(t, chans)
}
func (suite *ChannelsPagerIntgSuite) TestEnumerateChannelMessages() {
var (
t = suite.T()
ac = suite.its.ac.Channels()
)
ctx, flush := tester.NewContext(t)
defer flush()
msgs, du, err := ac.GetChannelMessagesDelta(
ctx,
suite.its.group.id,
suite.its.group.testContainerID,
"")
require.NoError(t, err, clues.ToCore(err))
require.NotEmpty(t, msgs)
require.NotZero(t, du.URL, "delta link")
require.True(t, du.Reset, "reset due to empty prev delta link")
msgs, du, err = ac.GetChannelMessagesDelta(
ctx,
suite.its.group.id,
suite.its.group.testContainerID,
du.URL)
require.NoError(t, err, clues.ToCore(err))
require.Empty(t, msgs, "should have no new messages from delta")
require.NotZero(t, du.URL, "delta link")
require.False(t, du.Reset, "prev delta link should be valid")
} }

View File

@ -39,13 +39,13 @@ func (suite *ContactsPagerIntgSuite) TestContacts_GetItemsInContainerByCollision
ctx, flush := tester.NewContext(t) ctx, flush := tester.NewContext(t)
defer flush() defer flush()
container, err := ac.GetContainerByID(ctx, suite.its.userID, "contacts") container, err := ac.GetContainerByID(ctx, suite.its.user.id, "contacts")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
conts, err := ac.Stable. conts, err := ac.Stable.
Client(). Client().
Users(). Users().
ByUserId(suite.its.userID). ByUserId(suite.its.user.id).
ContactFolders(). ContactFolders().
ByContactFolderId(ptr.Val(container.GetId())). ByContactFolderId(ptr.Val(container.GetId())).
Contacts(). Contacts().
@ -61,7 +61,7 @@ func (suite *ContactsPagerIntgSuite) TestContacts_GetItemsInContainerByCollision
expect := maps.Keys(expectM) expect := maps.Keys(expectM)
results, err := suite.its.ac.Contacts().GetItemsInContainerByCollisionKey(ctx, suite.its.userID, "contacts") results, err := suite.its.ac.Contacts().GetItemsInContainerByCollisionKey(ctx, suite.its.user.id, "contacts")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
require.Less(t, 0, len(results), "requires at least one result") require.Less(t, 0, len(results), "requires at least one result")
@ -91,13 +91,13 @@ func (suite *ContactsPagerIntgSuite) TestContacts_GetItemsIDsInContainer() {
ctx, flush := tester.NewContext(t) ctx, flush := tester.NewContext(t)
defer flush() defer flush()
container, err := ac.GetContainerByID(ctx, suite.its.userID, api.DefaultContacts) container, err := ac.GetContainerByID(ctx, suite.its.user.id, api.DefaultContacts)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
msgs, err := ac.Stable. msgs, err := ac.Stable.
Client(). Client().
Users(). Users().
ByUserId(suite.its.userID). ByUserId(suite.its.user.id).
ContactFolders(). ContactFolders().
ByContactFolderId(ptr.Val(container.GetId())). ByContactFolderId(ptr.Val(container.GetId())).
Contacts(). Contacts().
@ -112,7 +112,7 @@ func (suite *ContactsPagerIntgSuite) TestContacts_GetItemsIDsInContainer() {
} }
results, err := suite.its.ac.Contacts(). results, err := suite.its.ac.Contacts().
GetItemIDsInContainer(ctx, suite.its.userID, api.DefaultContacts) GetItemIDsInContainer(ctx, suite.its.user.id, api.DefaultContacts)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
require.Less(t, 0, len(results), "requires at least one result") require.Less(t, 0, len(results), "requires at least one result")
require.Equal(t, len(expect), len(results), "must have same count of items") require.Equal(t, len(expect), len(results), "must have same count of items")

View File

@ -141,7 +141,7 @@ func (suite *ContactsAPIIntgSuite) TestContacts_GetContainerByName() {
cc, err := suite.its.ac.Contacts().CreateContainer( cc, err := suite.its.ac.Contacts().CreateContainer(
ctx, ctx,
suite.its.userID, suite.its.user.id,
"", "",
rc.Location) rc.Location)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -168,7 +168,7 @@ func (suite *ContactsAPIIntgSuite) TestContacts_GetContainerByName() {
_, err := suite.its.ac. _, err := suite.its.ac.
Contacts(). Contacts().
GetContainerByName(ctx, suite.its.userID, "", test.name) GetContainerByName(ctx, suite.its.user.id, "", test.name)
test.expectErr(t, err, clues.ToCore(err)) test.expectErr(t, err, clues.ToCore(err))
}) })
} }

View File

@ -39,13 +39,13 @@ func (suite *DrivePagerIntgSuite) TestDrives_GetItemsInContainerByCollisionKey()
}{ }{
{ {
name: "user drive", name: "user drive",
driveID: suite.its.userDriveID, driveID: suite.its.user.driveID,
rootFolderID: suite.its.userDriveRootFolderID, rootFolderID: suite.its.user.driveRootFolderID,
}, },
{ {
name: "site drive", name: "site drive",
driveID: suite.its.siteDriveID, driveID: suite.its.site.driveID,
rootFolderID: suite.its.siteDriveRootFolderID, rootFolderID: suite.its.site.driveRootFolderID,
}, },
} }
for _, test := range table { for _, test := range table {
@ -75,7 +75,7 @@ func (suite *DrivePagerIntgSuite) TestDrives_GetItemsInContainerByCollisionKey()
t, t,
ims, ims,
"need at least one item to compare in user %s drive %s folder %s", "need at least one item to compare in user %s drive %s folder %s",
suite.its.userID, test.driveID, test.rootFolderID) suite.its.user.id, test.driveID, test.rootFolderID)
results, err := suite.its.ac. results, err := suite.its.ac.
Drives(). Drives().
@ -113,13 +113,13 @@ func (suite *DrivePagerIntgSuite) TestDrives_GetItemIDsInContainer() {
}{ }{
{ {
name: "user drive", name: "user drive",
driveID: suite.its.userDriveID, driveID: suite.its.user.driveID,
rootFolderID: suite.its.userDriveRootFolderID, rootFolderID: suite.its.user.driveRootFolderID,
}, },
{ {
name: "site drive", name: "site drive",
driveID: suite.its.siteDriveID, driveID: suite.its.site.driveID,
rootFolderID: suite.its.siteDriveRootFolderID, rootFolderID: suite.its.site.driveRootFolderID,
}, },
} }
for _, test := range table { for _, test := range table {
@ -149,7 +149,7 @@ func (suite *DrivePagerIntgSuite) TestDrives_GetItemIDsInContainer() {
t, t,
igv, igv,
"need at least one item to compare in user %s drive %s folder %s", "need at least one item to compare in user %s drive %s folder %s",
suite.its.userID, test.driveID, test.rootFolderID) suite.its.user.id, test.driveID, test.rootFolderID)
for _, itm := range igv { for _, itm := range igv {
expect[ptr.Val(itm.GetId())] = api.DriveItemIDType{ expect[ptr.Val(itm.GetId())] = api.DriveItemIDType{

View File

@ -76,8 +76,8 @@ func (suite *DriveAPIIntgSuite) TestDrives_PostItemInContainer() {
// generate a parent for the test data // generate a parent for the test data
parent, err := acd.PostItemInContainer( parent, err := acd.PostItemInContainer(
ctx, ctx,
suite.its.userDriveID, suite.its.user.driveID,
suite.its.userDriveRootFolderID, suite.its.user.driveRootFolderID,
newItem(rc.Location, true), newItem(rc.Location, true),
control.Replace) control.Replace)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
@ -86,7 +86,7 @@ func (suite *DriveAPIIntgSuite) TestDrives_PostItemInContainer() {
folder := newItem("collision", true) folder := newItem("collision", true)
origFolder, err := acd.PostItemInContainer( origFolder, err := acd.PostItemInContainer(
ctx, ctx,
suite.its.userDriveID, suite.its.user.driveID,
ptr.Val(parent.GetId()), ptr.Val(parent.GetId()),
folder, folder,
control.Copy) control.Copy)
@ -96,7 +96,7 @@ func (suite *DriveAPIIntgSuite) TestDrives_PostItemInContainer() {
file := newItem("collision.txt", false) file := newItem("collision.txt", false)
origFile, err := acd.PostItemInContainer( origFile, err := acd.PostItemInContainer(
ctx, ctx,
suite.its.userDriveID, suite.its.user.driveID,
ptr.Val(parent.GetId()), ptr.Val(parent.GetId()),
file, file,
control.Copy) control.Copy)
@ -211,7 +211,7 @@ func (suite *DriveAPIIntgSuite) TestDrives_PostItemInContainer() {
t := suite.T() t := suite.T()
i, err := acd.PostItemInContainer( i, err := acd.PostItemInContainer(
ctx, ctx,
suite.its.userDriveID, suite.its.user.driveID,
ptr.Val(parent.GetId()), ptr.Val(parent.GetId()),
test.postItem, test.postItem,
test.onCollision) test.onCollision)
@ -239,8 +239,8 @@ func (suite *DriveAPIIntgSuite) TestDrives_PostItemInContainer_replaceFolderRegr
// generate a folder for the test data // generate a folder for the test data
folder, err := acd.PostItemInContainer( folder, err := acd.PostItemInContainer(
ctx, ctx,
suite.its.userDriveID, suite.its.user.driveID,
suite.its.userDriveRootFolderID, suite.its.user.driveRootFolderID,
newItem(rc.Location, true), newItem(rc.Location, true),
// skip instead of replace here to get // skip instead of replace here to get
// an ErrItemAlreadyExistsConflict, just in case. // an ErrItemAlreadyExistsConflict, just in case.
@ -252,7 +252,7 @@ func (suite *DriveAPIIntgSuite) TestDrives_PostItemInContainer_replaceFolderRegr
file := newItem(fmt.Sprintf("collision_%d.txt", i), false) file := newItem(fmt.Sprintf("collision_%d.txt", i), false)
f, err := acd.PostItemInContainer( f, err := acd.PostItemInContainer(
ctx, ctx,
suite.its.userDriveID, suite.its.user.driveID,
ptr.Val(folder.GetId()), ptr.Val(folder.GetId()),
file, file,
control.Copy) control.Copy)
@ -263,7 +263,7 @@ func (suite *DriveAPIIntgSuite) TestDrives_PostItemInContainer_replaceFolderRegr
resultFolder, err := acd.PostItemInContainer( resultFolder, err := acd.PostItemInContainer(
ctx, ctx,
suite.its.userDriveID, suite.its.user.driveID,
ptr.Val(folder.GetParentReference().GetId()), ptr.Val(folder.GetParentReference().GetId()),
newItem(rc.Location, true), newItem(rc.Location, true),
control.Replace) control.Replace)
@ -274,7 +274,7 @@ func (suite *DriveAPIIntgSuite) TestDrives_PostItemInContainer_replaceFolderRegr
resultFileColl, err := acd.Stable. resultFileColl, err := acd.Stable.
Client(). Client().
Drives(). Drives().
ByDriveId(suite.its.userDriveID). ByDriveId(suite.its.user.driveID).
Items(). Items().
ByDriveItemId(ptr.Val(resultFolder.GetId())). ByDriveItemId(ptr.Val(resultFolder.GetId())).
Children(). Children().

View File

@ -39,13 +39,13 @@ func (suite *EventsPagerIntgSuite) TestEvents_GetItemsInContainerByCollisionKey(
ctx, flush := tester.NewContext(t) ctx, flush := tester.NewContext(t)
defer flush() defer flush()
container, err := ac.GetContainerByID(ctx, suite.its.userID, "calendar") container, err := ac.GetContainerByID(ctx, suite.its.user.id, "calendar")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
evts, err := ac.Stable. evts, err := ac.Stable.
Client(). Client().
Users(). Users().
ByUserId(suite.its.userID). ByUserId(suite.its.user.id).
Calendars(). Calendars().
ByCalendarId(ptr.Val(container.GetId())). ByCalendarId(ptr.Val(container.GetId())).
Events(). Events().
@ -63,7 +63,7 @@ func (suite *EventsPagerIntgSuite) TestEvents_GetItemsInContainerByCollisionKey(
results, err := suite.its.ac. results, err := suite.its.ac.
Events(). Events().
GetItemsInContainerByCollisionKey(ctx, suite.its.userID, "calendar") GetItemsInContainerByCollisionKey(ctx, suite.its.user.id, "calendar")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
require.Less(t, 0, len(results), "requires at least one result") require.Less(t, 0, len(results), "requires at least one result")

View File

@ -289,7 +289,7 @@ func (suite *EventsAPIIntgSuite) TestEvents_canFindNonStandardFolder() {
ac := suite.its.ac.Events() ac := suite.its.ac.Events()
rc := testdata.DefaultRestoreConfig("api_calendar_discovery") rc := testdata.DefaultRestoreConfig("api_calendar_discovery")
cal, err := ac.CreateContainer(ctx, suite.its.userID, "", rc.Location) cal, err := ac.CreateContainer(ctx, suite.its.user.id, "", rc.Location)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
var ( var (
@ -306,7 +306,7 @@ func (suite *EventsAPIIntgSuite) TestEvents_canFindNonStandardFolder() {
err = ac.EnumerateContainers( err = ac.EnumerateContainers(
ctx, ctx,
suite.its.userID, suite.its.user.id,
"Calendar", "Calendar",
findContainer, findContainer,
fault.New(true)) fault.New(true))
@ -342,7 +342,7 @@ func (suite *EventsAPIIntgSuite) TestEvents_GetContainerByName() {
_, err := suite.its.ac. _, err := suite.its.ac.
Events(). Events().
GetContainerByName(ctx, suite.its.userID, "", test.name) GetContainerByName(ctx, suite.its.user.id, "", test.name)
test.expectErr(t, err, clues.ToCore(err)) test.expectErr(t, err, clues.ToCore(err))
}) })
} }

View File

@ -112,7 +112,7 @@ func (suite *GroupsIntgSuite) TestGetAll() {
func (suite *GroupsIntgSuite) TestGroups_GetByID() { func (suite *GroupsIntgSuite) TestGroups_GetByID() {
var ( var (
groupID = suite.its.groupID groupID = suite.its.group.id
groupsAPI = suite.its.ac.Groups() groupsAPI = suite.its.ac.Groups()
) )

View File

@ -74,16 +74,19 @@ func parseableToMap(t *testing.T, thing serialization.Parsable) map[string]any {
// Suite Setup // Suite Setup
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
type ids struct {
id string
driveID string
driveRootFolderID string
testContainerID string
}
type intgTesterSetup struct { type intgTesterSetup struct {
ac api.Client ac api.Client
gockAC api.Client gockAC api.Client
userID string user ids
userDriveID string site ids
userDriveRootFolderID string group ids
siteID string
siteDriveID string
siteDriveRootFolderID string
groupID string
} }
func newIntegrationTesterSetup(t *testing.T) intgTesterSetup { func newIntegrationTesterSetup(t *testing.T) intgTesterSetup {
@ -106,42 +109,47 @@ func newIntegrationTesterSetup(t *testing.T) intgTesterSetup {
// user drive // user drive
its.userID = tconfig.M365UserID(t) its.user.id = tconfig.M365UserID(t)
userDrive, err := its.ac.Users().GetDefaultDrive(ctx, its.userID) userDrive, err := its.ac.Users().GetDefaultDrive(ctx, its.user.id)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
its.userDriveID = ptr.Val(userDrive.GetId()) its.user.driveID = ptr.Val(userDrive.GetId())
userDriveRootFolder, err := its.ac.Drives().GetRootFolder(ctx, its.userDriveID) userDriveRootFolder, err := its.ac.Drives().GetRootFolder(ctx, its.user.driveID)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
its.userDriveRootFolderID = ptr.Val(userDriveRootFolder.GetId()) its.user.driveRootFolderID = ptr.Val(userDriveRootFolder.GetId())
its.siteID = tconfig.M365SiteID(t)
// site // site
siteDrive, err := its.ac.Sites().GetDefaultDrive(ctx, its.siteID) its.site.id = tconfig.M365SiteID(t)
siteDrive, err := its.ac.Sites().GetDefaultDrive(ctx, its.site.id)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
its.siteDriveID = ptr.Val(siteDrive.GetId()) its.site.driveID = ptr.Val(siteDrive.GetId())
siteDriveRootFolder, err := its.ac.Drives().GetRootFolder(ctx, its.siteDriveID) siteDriveRootFolder, err := its.ac.Drives().GetRootFolder(ctx, its.site.driveID)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
its.siteDriveRootFolderID = ptr.Val(siteDriveRootFolder.GetId()) its.site.driveRootFolderID = ptr.Val(siteDriveRootFolder.GetId())
// group // groups/teams
// use of the TeamID is intentional here, so that we are assured // use of the TeamID is intentional here, so that we are assured
// the group has full usage of the teams api. // the group has full usage of the teams api.
its.groupID = tconfig.M365TeamID(t) its.group.id = tconfig.M365TeamID(t)
team, err := its.ac.Groups().GetByID(ctx, its.groupID) channel, err := its.ac.Channels().
GetChannelByName(
ctx,
its.group.id,
"Test")
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
require.Equal(t, "Test", ptr.Val(channel.GetDisplayName()))
its.groupID = ptr.Val(team.GetId()) its.group.testContainerID = ptr.Val(channel.GetId())
return its return its
} }

View File

@ -41,7 +41,7 @@ func (suite *ListsAPIIntgSuite) TestLists_PostDrive() {
var ( var (
acl = suite.its.ac.Lists() acl = suite.its.ac.Lists()
driveName = testdata.DefaultRestoreConfig("list_api_post_drive").Location driveName = testdata.DefaultRestoreConfig("list_api_post_drive").Location
siteID = suite.its.siteID siteID = suite.its.site.id
) )
// first post, should have no errors // first post, should have no errors

View File

@ -40,13 +40,13 @@ func (suite *MailPagerIntgSuite) TestMail_GetItemsInContainerByCollisionKey() {
ctx, flush := tester.NewContext(t) ctx, flush := tester.NewContext(t)
defer flush() defer flush()
container, err := ac.GetContainerByID(ctx, suite.its.userID, api.MailInbox) container, err := ac.GetContainerByID(ctx, suite.its.user.id, api.MailInbox)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
msgs, err := ac.Stable. msgs, err := ac.Stable.
Client(). Client().
Users(). Users().
ByUserId(suite.its.userID). ByUserId(suite.its.user.id).
MailFolders(). MailFolders().
ByMailFolderId(ptr.Val(container.GetId())). ByMailFolderId(ptr.Val(container.GetId())).
Messages(). Messages().
@ -62,7 +62,7 @@ func (suite *MailPagerIntgSuite) TestMail_GetItemsInContainerByCollisionKey() {
expect := maps.Keys(expectM) expect := maps.Keys(expectM)
results, err := suite.its.ac.Mail().GetItemsInContainerByCollisionKey(ctx, suite.its.userID, api.MailInbox) results, err := suite.its.ac.Mail().GetItemsInContainerByCollisionKey(ctx, suite.its.user.id, api.MailInbox)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
require.Less(t, 0, len(results), "requires at least one result") require.Less(t, 0, len(results), "requires at least one result")
@ -101,7 +101,7 @@ func (suite *MailPagerIntgSuite) TestMail_GetItemsIDsInContainer() {
msgs, err := ac.Stable. msgs, err := ac.Stable.
Client(). Client().
Users(). Users().
ByUserId(suite.its.userID). ByUserId(suite.its.user.id).
MailFolders(). MailFolders().
ByMailFolderId(api.MailInbox). ByMailFolderId(api.MailInbox).
Messages(). Messages().
@ -116,7 +116,7 @@ func (suite *MailPagerIntgSuite) TestMail_GetItemsIDsInContainer() {
} }
results, err := suite.its.ac.Mail(). results, err := suite.its.ac.Mail().
GetItemIDsInContainer(ctx, suite.its.userID, api.MailInbox) GetItemIDsInContainer(ctx, suite.its.user.id, api.MailInbox)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
require.Less(t, 0, len(results), "requires at least one result") require.Less(t, 0, len(results), "requires at least one result")
require.Equal(t, len(expect), len(results), "must have same count of items") require.Equal(t, len(expect), len(results), "must have same count of items")

View File

@ -414,7 +414,7 @@ func (suite *MailAPIIntgSuite) TestMail_GetContainerByName() {
ctx, flush := tester.NewContext(t) ctx, flush := tester.NewContext(t)
defer flush() defer flush()
parent, err := acm.CreateContainer(ctx, suite.its.userID, "msgfolderroot", rc.Location) parent, err := acm.CreateContainer(ctx, suite.its.user.id, "msgfolderroot", rc.Location)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
table := []struct { table := []struct {
@ -448,7 +448,7 @@ func (suite *MailAPIIntgSuite) TestMail_GetContainerByName() {
ctx, flush := tester.NewContext(t) ctx, flush := tester.NewContext(t)
defer flush() defer flush()
_, err := acm.GetContainerByName(ctx, suite.its.userID, test.parentContainerID, test.name) _, err := acm.GetContainerByName(ctx, suite.its.user.id, test.parentContainerID, test.name)
test.expectErr(t, err, clues.ToCore(err)) test.expectErr(t, err, clues.ToCore(err))
}) })
} }
@ -460,10 +460,10 @@ func (suite *MailAPIIntgSuite) TestMail_GetContainerByName() {
ctx, flush := tester.NewContext(t) ctx, flush := tester.NewContext(t)
defer flush() defer flush()
child, err := acm.CreateContainer(ctx, suite.its.userID, pid, rc.Location) child, err := acm.CreateContainer(ctx, suite.its.user.id, pid, rc.Location)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
result, err := acm.GetContainerByName(ctx, suite.its.userID, pid, rc.Location) result, err := acm.GetContainerByName(ctx, suite.its.user.id, pid, rc.Location)
assert.NoError(t, err, clues.ToCore(err)) assert.NoError(t, err, clues.ToCore(err))
assert.Equal(t, ptr.Val(child.GetId()), ptr.Val(result.GetId())) assert.Equal(t, ptr.Val(child.GetId()), ptr.Val(result.GetId()))
}) })

View File

@ -262,7 +262,7 @@ func (suite *UsersIntgSuite) TestUsers_GetInfo_quotaExceeded() {
gock.EnableNetworking() gock.EnableNetworking()
gock.New(graphAPIHostURL). gock.New(graphAPIHostURL).
// Wildcard match on the inbox folder ID. // Wildcard match on the inbox folder ID.
Get(v1APIURLPath("users", suite.its.userID, "mailFolders", "(.*)", "messages", "delta")). Get(v1APIURLPath("users", suite.its.user.id, "mailFolders", "(.*)", "messages", "delta")).
Reply(403). Reply(403).
SetHeaders( SetHeaders(
map[string]string{ map[string]string{
@ -272,7 +272,7 @@ func (suite *UsersIntgSuite) TestUsers_GetInfo_quotaExceeded() {
). ).
BodyString(`{"error":{"code":"ErrorQuotaExceeded","message":"The process failed to get the correct properties."}}`) BodyString(`{"error":{"code":"ErrorQuotaExceeded","message":"The process failed to get the correct properties."}}`)
output, err := suite.its.gockAC.Users().GetInfo(ctx, suite.its.userID) output, err := suite.its.gockAC.Users().GetInfo(ctx, suite.its.user.id)
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
assert.True(t, output.Mailbox.QuotaExceeded) assert.True(t, output.Mailbox.QuotaExceeded)