centralize basic backup test, add teamschats
adds teamchats to the integration backup tests. Moves the common basic test func into a shared package and calls that test with exchange, groups, and teamchats.
This commit is contained in:
parent
befec6d341
commit
4efa7762c9
@ -396,3 +396,120 @@ func RunMergeBaseGroupsUpdate(
|
|||||||
"cached items")
|
"cached items")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RunBasicBackupTest(
|
||||||
|
suite tester.Suite,
|
||||||
|
sel selectors.Selector,
|
||||||
|
) {
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
ctx, flush := tester.NewContext(t)
|
||||||
|
defer flush()
|
||||||
|
|
||||||
|
var (
|
||||||
|
mb = evmock.NewBus()
|
||||||
|
counter = count.New()
|
||||||
|
opts = control.DefaultOptions()
|
||||||
|
whatSet = deeTD.CategoryFromRepoRef
|
||||||
|
)
|
||||||
|
|
||||||
|
bo, bod := PrepNewTestBackupOp(t, ctx, mb, sel, opts, version.Backup, counter)
|
||||||
|
defer bod.Close(t, ctx)
|
||||||
|
|
||||||
|
reasons, err := bod.Sel.Reasons(bod.Acct.ID(), false)
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
RunAndCheckBackup(t, ctx, &bo, mb, false)
|
||||||
|
|
||||||
|
for _, reason := range reasons {
|
||||||
|
CheckBackupIsInManifests(
|
||||||
|
t,
|
||||||
|
ctx,
|
||||||
|
bod.KW,
|
||||||
|
bod.SW,
|
||||||
|
&bo,
|
||||||
|
bod.Sel,
|
||||||
|
bod.Sel.ID(),
|
||||||
|
reason.Category())
|
||||||
|
}
|
||||||
|
|
||||||
|
_, expectDeets := deeTD.GetDeetsInBackup(
|
||||||
|
t,
|
||||||
|
ctx,
|
||||||
|
bo.Results.BackupID,
|
||||||
|
bod.Acct.ID(),
|
||||||
|
bod.Sel.ID(),
|
||||||
|
sel.PathService(),
|
||||||
|
whatSet,
|
||||||
|
bod.KMS,
|
||||||
|
bod.SSS)
|
||||||
|
deeTD.CheckBackupDetails(
|
||||||
|
t,
|
||||||
|
ctx,
|
||||||
|
bo.Results.BackupID,
|
||||||
|
whatSet,
|
||||||
|
bod.KMS,
|
||||||
|
bod.SSS,
|
||||||
|
expectDeets,
|
||||||
|
false)
|
||||||
|
|
||||||
|
// Basic, happy path incremental test. No changes are dictated or expected.
|
||||||
|
// This only tests that an incremental backup is runnable at all, and that it
|
||||||
|
// produces fewer results than the last backup.
|
||||||
|
//
|
||||||
|
// Incremental testing for conversations is limited because of API restrictions.
|
||||||
|
// Since graph doesn't provide us a way to programmatically delete conversations,
|
||||||
|
// or create new conversations without a delegated token, we can't do incremental
|
||||||
|
// testing with newly added items.
|
||||||
|
incMB := evmock.NewBus()
|
||||||
|
incBO := NewTestBackupOp(
|
||||||
|
t,
|
||||||
|
ctx,
|
||||||
|
bod,
|
||||||
|
incMB,
|
||||||
|
opts,
|
||||||
|
count.New())
|
||||||
|
|
||||||
|
RunAndCheckBackup(t, ctx, &incBO, incMB, true)
|
||||||
|
|
||||||
|
for _, reason := range reasons {
|
||||||
|
CheckBackupIsInManifests(
|
||||||
|
t,
|
||||||
|
ctx,
|
||||||
|
bod.KW,
|
||||||
|
bod.SW,
|
||||||
|
&incBO,
|
||||||
|
bod.Sel,
|
||||||
|
bod.Sel.ID(),
|
||||||
|
reason.Category())
|
||||||
|
}
|
||||||
|
|
||||||
|
_, expectDeets = deeTD.GetDeetsInBackup(
|
||||||
|
t,
|
||||||
|
ctx,
|
||||||
|
incBO.Results.BackupID,
|
||||||
|
bod.Acct.ID(),
|
||||||
|
bod.Sel.ID(),
|
||||||
|
bod.Sel.PathService(),
|
||||||
|
whatSet,
|
||||||
|
bod.KMS,
|
||||||
|
bod.SSS)
|
||||||
|
deeTD.CheckBackupDetails(
|
||||||
|
t,
|
||||||
|
ctx,
|
||||||
|
incBO.Results.BackupID,
|
||||||
|
whatSet,
|
||||||
|
bod.KMS,
|
||||||
|
bod.SSS,
|
||||||
|
expectDeets,
|
||||||
|
false)
|
||||||
|
|
||||||
|
assert.NotZero(
|
||||||
|
t,
|
||||||
|
incBO.Results.Counts[string(count.PersistedCachedFiles)],
|
||||||
|
"cached items")
|
||||||
|
assert.Greater(t, bo.Results.ItemsWritten, incBO.Results.ItemsWritten, "incremental items written")
|
||||||
|
assert.Greater(t, bo.Results.BytesRead, incBO.Results.BytesRead, "incremental bytes read")
|
||||||
|
assert.Greater(t, bo.Results.BytesUploaded, incBO.Results.BytesUploaded, "incremental bytes uploaded")
|
||||||
|
assert.Equal(t, 1, incMB.TimesCalled[events.BackupEnd], "incremental backup-end events")
|
||||||
|
}
|
||||||
|
|||||||
@ -70,7 +70,7 @@ func MetadataFileNames(cat path.CategoryType) [][]string {
|
|||||||
|
|
||||||
// TestBackup_Run ensures that Integration Testing works
|
// TestBackup_Run ensures that Integration Testing works
|
||||||
// for the following scopes: Contacts, Events, and Mail
|
// for the following scopes: Contacts, Events, and Mail
|
||||||
func (suite *ExchangeBackupIntgSuite) TestBackup_Run_exchange() {
|
func (suite *ExchangeBackupIntgSuite) TestBackup_Run_basicBackup() {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
selector func() *selectors.ExchangeBackup
|
selector func() *selectors.ExchangeBackup
|
||||||
@ -112,124 +112,7 @@ func (suite *ExchangeBackupIntgSuite) TestBackup_Run_exchange() {
|
|||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
t := suite.T()
|
RunBasicBackupTest(suite, test.selector().Selector)
|
||||||
|
|
||||||
ctx, flush := tester.NewContext(t)
|
|
||||||
defer flush()
|
|
||||||
|
|
||||||
var (
|
|
||||||
mb = evmock.NewBus()
|
|
||||||
counter = count.New()
|
|
||||||
sel = test.selector().Selector
|
|
||||||
opts = control.DefaultOptions()
|
|
||||||
whatSet = deeTD.CategoryFromRepoRef
|
|
||||||
)
|
|
||||||
|
|
||||||
bo, bod := PrepNewTestBackupOp(t, ctx, mb, sel, opts, version.Backup, counter)
|
|
||||||
defer bod.Close(t, ctx)
|
|
||||||
|
|
||||||
sel = bod.Sel
|
|
||||||
|
|
||||||
userID := sel.ID()
|
|
||||||
|
|
||||||
m365, err := bod.Acct.M365Config()
|
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
|
||||||
|
|
||||||
// run the tests
|
|
||||||
RunAndCheckBackup(t, ctx, &bo, mb, false)
|
|
||||||
CheckBackupIsInManifests(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
bod.KW,
|
|
||||||
bod.SW,
|
|
||||||
&bo,
|
|
||||||
sel,
|
|
||||||
userID,
|
|
||||||
test.category)
|
|
||||||
CheckMetadataFilesExist(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
bo.Results.BackupID,
|
|
||||||
bod.KW,
|
|
||||||
bod.KMS,
|
|
||||||
m365.AzureTenantID,
|
|
||||||
userID,
|
|
||||||
path.ExchangeService,
|
|
||||||
map[path.CategoryType][][]string{test.category: test.metadataFiles})
|
|
||||||
|
|
||||||
_, expectDeets := deeTD.GetDeetsInBackup(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
bo.Results.BackupID,
|
|
||||||
bod.Acct.ID(),
|
|
||||||
userID,
|
|
||||||
path.ExchangeService,
|
|
||||||
whatSet,
|
|
||||||
bod.KMS,
|
|
||||||
bod.SSS)
|
|
||||||
deeTD.CheckBackupDetails(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
bo.Results.BackupID,
|
|
||||||
whatSet,
|
|
||||||
bod.KMS,
|
|
||||||
bod.SSS,
|
|
||||||
expectDeets,
|
|
||||||
false)
|
|
||||||
|
|
||||||
// Basic, happy path incremental test. No changes are dictated or expected.
|
|
||||||
// This only tests that an incremental backup is runnable at all, and that it
|
|
||||||
// produces fewer results than the last backup.
|
|
||||||
var (
|
|
||||||
incMB = evmock.NewBus()
|
|
||||||
incBO = NewTestBackupOp(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
bod,
|
|
||||||
incMB,
|
|
||||||
opts,
|
|
||||||
counter)
|
|
||||||
)
|
|
||||||
|
|
||||||
RunAndCheckBackup(t, ctx, &incBO, incMB, true)
|
|
||||||
CheckBackupIsInManifests(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
bod.KW,
|
|
||||||
bod.SW,
|
|
||||||
&incBO,
|
|
||||||
sel,
|
|
||||||
userID,
|
|
||||||
test.category)
|
|
||||||
CheckMetadataFilesExist(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
incBO.Results.BackupID,
|
|
||||||
bod.KW,
|
|
||||||
bod.KMS,
|
|
||||||
m365.AzureTenantID,
|
|
||||||
userID,
|
|
||||||
path.ExchangeService,
|
|
||||||
map[path.CategoryType][][]string{test.category: test.metadataFiles})
|
|
||||||
deeTD.CheckBackupDetails(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
incBO.Results.BackupID,
|
|
||||||
whatSet,
|
|
||||||
bod.KMS,
|
|
||||||
bod.SSS,
|
|
||||||
expectDeets,
|
|
||||||
false)
|
|
||||||
|
|
||||||
// do some additional checks to ensure the incremental dealt with fewer items.
|
|
||||||
assert.Greater(t, bo.Results.ItemsWritten, incBO.Results.ItemsWritten, "incremental items written")
|
|
||||||
assert.Greater(t, bo.Results.ItemsRead, incBO.Results.ItemsRead, "incremental items read")
|
|
||||||
assert.Greater(t, bo.Results.BytesRead, incBO.Results.BytesRead, "incremental bytes read")
|
|
||||||
assert.Greater(t, bo.Results.BytesUploaded, incBO.Results.BytesUploaded, "incremental bytes uploaded")
|
|
||||||
assert.Equal(t, bo.Results.ResourceOwners, incBO.Results.ResourceOwners, "incremental backup resource owner")
|
|
||||||
assert.NoError(t, incBO.Errors.Failure(), "incremental non-recoverable error", clues.ToCore(bo.Errors.Failure()))
|
|
||||||
assert.Empty(t, incBO.Errors.Recovered(), "count incremental recoverable/iteration errors")
|
|
||||||
assert.Equal(t, 1, incMB.TimesCalled[events.BackupEnd], "incremental backup-end events")
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,21 +4,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"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/events"
|
|
||||||
evmock "github.com/alcionai/corso/src/internal/events/mock"
|
|
||||||
"github.com/alcionai/corso/src/internal/m365/collection/drive"
|
"github.com/alcionai/corso/src/internal/m365/collection/drive"
|
||||||
. "github.com/alcionai/corso/src/internal/operations/test/m365"
|
. "github.com/alcionai/corso/src/internal/operations/test/m365"
|
||||||
"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"
|
||||||
"github.com/alcionai/corso/src/internal/version"
|
|
||||||
deeTD "github.com/alcionai/corso/src/pkg/backup/details/testdata"
|
|
||||||
"github.com/alcionai/corso/src/pkg/control"
|
"github.com/alcionai/corso/src/pkg/control"
|
||||||
"github.com/alcionai/corso/src/pkg/count"
|
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
"github.com/alcionai/corso/src/pkg/selectors"
|
"github.com/alcionai/corso/src/pkg/selectors"
|
||||||
selTD "github.com/alcionai/corso/src/pkg/selectors/testdata"
|
selTD "github.com/alcionai/corso/src/pkg/selectors/testdata"
|
||||||
@ -190,124 +182,14 @@ func runGroupsIncrementalBackupTests(
|
|||||||
true)
|
true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *GroupsBackupIntgSuite) TestBackup_Run_groupsBasic() {
|
func (suite *GroupsBackupIntgSuite) TestBackup_Run_basicBackup() {
|
||||||
t := suite.T()
|
sel := selectors.NewGroupsBackup([]string{suite.its.Group.ID})
|
||||||
|
|
||||||
ctx, flush := tester.NewContext(t)
|
|
||||||
defer flush()
|
|
||||||
|
|
||||||
var (
|
|
||||||
mb = evmock.NewBus()
|
|
||||||
counter = count.New()
|
|
||||||
sel = selectors.NewGroupsBackup([]string{suite.its.Group.ID})
|
|
||||||
opts = control.DefaultOptions()
|
|
||||||
whatSet = deeTD.CategoryFromRepoRef
|
|
||||||
)
|
|
||||||
|
|
||||||
sel.Include(
|
sel.Include(
|
||||||
selTD.GroupsBackupLibraryFolderScope(sel),
|
selTD.GroupsBackupLibraryFolderScope(sel),
|
||||||
selTD.GroupsBackupChannelScope(sel),
|
selTD.GroupsBackupChannelScope(sel),
|
||||||
selTD.GroupsBackupConversationScope(sel))
|
selTD.GroupsBackupConversationScope(sel))
|
||||||
|
|
||||||
bo, bod := PrepNewTestBackupOp(t, ctx, mb, sel.Selector, opts, version.Backup, counter)
|
RunBasicBackupTest(suite, sel.Selector)
|
||||||
defer bod.Close(t, ctx)
|
|
||||||
|
|
||||||
reasons, err := bod.Sel.Reasons(bod.Acct.ID(), false)
|
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
|
||||||
|
|
||||||
RunAndCheckBackup(t, ctx, &bo, mb, false)
|
|
||||||
|
|
||||||
for _, reason := range reasons {
|
|
||||||
CheckBackupIsInManifests(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
bod.KW,
|
|
||||||
bod.SW,
|
|
||||||
&bo,
|
|
||||||
bod.Sel,
|
|
||||||
bod.Sel.ID(),
|
|
||||||
reason.Category())
|
|
||||||
}
|
|
||||||
|
|
||||||
_, expectDeets := deeTD.GetDeetsInBackup(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
bo.Results.BackupID,
|
|
||||||
bod.Acct.ID(),
|
|
||||||
bod.Sel.ID(),
|
|
||||||
path.GroupsService,
|
|
||||||
whatSet,
|
|
||||||
bod.KMS,
|
|
||||||
bod.SSS)
|
|
||||||
deeTD.CheckBackupDetails(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
bo.Results.BackupID,
|
|
||||||
whatSet,
|
|
||||||
bod.KMS,
|
|
||||||
bod.SSS,
|
|
||||||
expectDeets,
|
|
||||||
false)
|
|
||||||
|
|
||||||
// Basic, happy path incremental test. No changes are dictated or expected.
|
|
||||||
// This only tests that an incremental backup is runnable at all, and that it
|
|
||||||
// produces fewer results than the last backup.
|
|
||||||
//
|
|
||||||
// Incremental testing for conversations is limited because of API restrictions.
|
|
||||||
// Since graph doesn't provide us a way to programmatically delete conversations,
|
|
||||||
// or create new conversations without a delegated token, we can't do incremental
|
|
||||||
// testing with newly added items.
|
|
||||||
incMB := evmock.NewBus()
|
|
||||||
incBO := NewTestBackupOp(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
bod,
|
|
||||||
incMB,
|
|
||||||
opts,
|
|
||||||
count.New())
|
|
||||||
|
|
||||||
RunAndCheckBackup(t, ctx, &incBO, incMB, true)
|
|
||||||
|
|
||||||
for _, reason := range reasons {
|
|
||||||
CheckBackupIsInManifests(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
bod.KW,
|
|
||||||
bod.SW,
|
|
||||||
&incBO,
|
|
||||||
bod.Sel,
|
|
||||||
bod.Sel.ID(),
|
|
||||||
reason.Category())
|
|
||||||
}
|
|
||||||
|
|
||||||
_, expectDeets = deeTD.GetDeetsInBackup(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
incBO.Results.BackupID,
|
|
||||||
bod.Acct.ID(),
|
|
||||||
bod.Sel.ID(),
|
|
||||||
bod.Sel.PathService(),
|
|
||||||
whatSet,
|
|
||||||
bod.KMS,
|
|
||||||
bod.SSS)
|
|
||||||
deeTD.CheckBackupDetails(
|
|
||||||
t,
|
|
||||||
ctx,
|
|
||||||
incBO.Results.BackupID,
|
|
||||||
whatSet,
|
|
||||||
bod.KMS,
|
|
||||||
bod.SSS,
|
|
||||||
expectDeets,
|
|
||||||
false)
|
|
||||||
|
|
||||||
assert.NotZero(
|
|
||||||
t,
|
|
||||||
incBO.Results.Counts[string(count.PersistedCachedFiles)],
|
|
||||||
"cached items")
|
|
||||||
assert.Greater(t, bo.Results.ItemsWritten, incBO.Results.ItemsWritten, "incremental items written")
|
|
||||||
assert.Greater(t, bo.Results.BytesRead, incBO.Results.BytesRead, "incremental bytes read")
|
|
||||||
assert.Greater(t, bo.Results.BytesUploaded, incBO.Results.BytesUploaded, "incremental bytes uploaded")
|
|
||||||
assert.Equal(t, 1, incMB.TimesCalled[events.BackupEnd], "incremental backup-end events")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupsBackupNightlyIntgSuite struct {
|
type GroupsBackupNightlyIntgSuite struct {
|
||||||
|
|||||||
@ -0,0 +1,73 @@
|
|||||||
|
package teamschats_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
. "github.com/alcionai/corso/src/internal/operations/test/m365"
|
||||||
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
|
"github.com/alcionai/corso/src/internal/tester/tconfig"
|
||||||
|
"github.com/alcionai/corso/src/pkg/selectors"
|
||||||
|
selTD "github.com/alcionai/corso/src/pkg/selectors/testdata"
|
||||||
|
storeTD "github.com/alcionai/corso/src/pkg/storage/testdata"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TeamsChatsBackupIntgSuite struct {
|
||||||
|
tester.Suite
|
||||||
|
its IntgTesterSetup
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTeamsChatsBackupIntgSuite(t *testing.T) {
|
||||||
|
suite.Run(t, &TeamsChatsBackupIntgSuite{
|
||||||
|
Suite: tester.NewIntegrationSuite(
|
||||||
|
t,
|
||||||
|
[][]string{tconfig.M365AcctCredEnvs, storeTD.AWSStorageCredEnvs}),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *TeamsChatsBackupIntgSuite) SetupSuite() {
|
||||||
|
suite.its = NewIntegrationTesterSetup(suite.T())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *TeamsChatsBackupIntgSuite) TestBackup_Run_basicBackup() {
|
||||||
|
sel := selectors.NewTeamsChatsBackup([]string{suite.its.User.ID})
|
||||||
|
sel.Include(selTD.TeamsChatsBackupChatScope(sel))
|
||||||
|
|
||||||
|
RunBasicBackupTest(suite, sel.Selector)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// nightly tests
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type TeamsChatsBackupNightlyIntgSuite struct {
|
||||||
|
tester.Suite
|
||||||
|
its IntgTesterSetup
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTeamsChatsBackupNightlyIntgSuite(t *testing.T) {
|
||||||
|
suite.Run(t, &TeamsChatsBackupNightlyIntgSuite{
|
||||||
|
Suite: tester.NewNightlySuite(
|
||||||
|
t,
|
||||||
|
[][]string{tconfig.M365AcctCredEnvs, storeTD.AWSStorageCredEnvs}),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *TeamsChatsBackupNightlyIntgSuite) SetupSuite() {
|
||||||
|
suite.its = NewIntegrationTesterSetup(suite.T())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *TeamsChatsBackupNightlyIntgSuite) TestBackup_Run_teamschatsVersion9MergeBase() {
|
||||||
|
sel := selectors.NewTeamsChatsBackup([]string{suite.its.User.ID})
|
||||||
|
sel.Include(selTD.TeamsChatsBackupChatScope(sel))
|
||||||
|
|
||||||
|
RunMergeBaseGroupsUpdate(suite, sel.Selector, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *TeamsChatsBackupNightlyIntgSuite) TestBackup_Run_teamschatsVersion9AssistBases() {
|
||||||
|
sel := selectors.NewTeamsChatsBackup([]string{suite.its.User.ID})
|
||||||
|
sel.Include(selTD.TeamsChatsBackupChatScope(sel))
|
||||||
|
|
||||||
|
RunDriveAssistBaseGroupsUpdate(suite, sel.Selector, false)
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user