Backup details list exchange tests (#945)
## Description Add tests for the `backup list exchange` subcommand. Tests mostly center around indirectly testing how selectors are created and used in this subcommand by checking the output of running the `Reduce` call on a known set of `details.DetailsEntry`s. Also check various error cases Tests for invalid formats of flag values are disabled as that code does not currently exist. These tests can be enabled when #943 is resolved ## 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:
parent
4d02650f99
commit
824f02469c
@ -1,6 +1,8 @@
|
||||
package backup
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
@ -11,6 +13,7 @@ import (
|
||||
"github.com/alcionai/corso/src/cli/utils"
|
||||
"github.com/alcionai/corso/src/internal/model"
|
||||
"github.com/alcionai/corso/src/pkg/backup"
|
||||
"github.com/alcionai/corso/src/pkg/backup/details"
|
||||
"github.com/alcionai/corso/src/pkg/control"
|
||||
"github.com/alcionai/corso/src/pkg/repository"
|
||||
"github.com/alcionai/corso/src/pkg/selectors"
|
||||
@ -353,11 +356,6 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
|
||||
defer utils.CloseRepo(ctx, r)
|
||||
|
||||
d, _, err := r.BackupDetails(ctx, backupID)
|
||||
if err != nil {
|
||||
return Only(ctx, errors.Wrap(err, "Failed to get backup details in the repository"))
|
||||
}
|
||||
|
||||
opts := utils.ExchangeOpts{
|
||||
Contacts: contact,
|
||||
ContactFolders: contactFolder,
|
||||
@ -378,6 +376,34 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
EventSubject: eventSubject,
|
||||
}
|
||||
|
||||
ds, err := runDetailsExchangeCmd(ctx, r, backupID, opts)
|
||||
if err != nil {
|
||||
return Only(ctx, err)
|
||||
}
|
||||
|
||||
if len(ds.Entries) == 0 {
|
||||
Info(ctx, selectors.ErrorNoMatchingItems)
|
||||
return nil
|
||||
}
|
||||
|
||||
ds.PrintEntries(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// runDetailsExchangeCmd actually performs the lookup in backup details. Assumes
|
||||
// len(backupID) > 0.
|
||||
func runDetailsExchangeCmd(
|
||||
ctx context.Context,
|
||||
r repository.BackupGetter,
|
||||
backupID string,
|
||||
opts utils.ExchangeOpts,
|
||||
) (*details.Details, error) {
|
||||
d, _, err := r.BackupDetails(ctx, backupID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to get backup details in the repository")
|
||||
}
|
||||
|
||||
sel := selectors.NewExchangeRestore()
|
||||
utils.IncludeExchangeRestoreDataSelectors(sel, opts)
|
||||
utils.FilterExchangeRestoreInfoSelectors(sel, opts)
|
||||
@ -387,15 +413,7 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
sel.Include(sel.Users(selectors.Any()))
|
||||
}
|
||||
|
||||
ds := sel.Reduce(ctx, d)
|
||||
if len(ds.Entries) == 0 {
|
||||
Info(ctx, selectors.ErrorNoMatchingItems)
|
||||
return nil
|
||||
}
|
||||
|
||||
ds.PrintEntries(ctx)
|
||||
|
||||
return nil
|
||||
return sel.Reduce(ctx, d), nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package backup
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@ -9,6 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/alcionai/corso/src/cli/utils"
|
||||
"github.com/alcionai/corso/src/cli/utils/testdata"
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
)
|
||||
|
||||
@ -214,3 +216,56 @@ func (suite *ExchangeSuite) TestExchangeBackupCreateSelectors() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *ExchangeSuite) TestExchangeBackupDetailsSelectors() {
|
||||
ctx := context.Background()
|
||||
|
||||
for _, test := range testdata.ExchangeOptionDetailLookups {
|
||||
suite.T().Run(test.Name, func(t *testing.T) {
|
||||
output, err := runDetailsExchangeCmd(
|
||||
ctx,
|
||||
test.BackupGetter,
|
||||
"backup-ID",
|
||||
test.Opts,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.ElementsMatch(t, test.Expected, output.Entries)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *ExchangeSuite) TestExchangeBackupDetailsSelectorsBadBackupID() {
|
||||
t := suite.T()
|
||||
ctx := context.Background()
|
||||
backupGetter := &testdata.MockBackupGetter{}
|
||||
|
||||
output, err := runDetailsExchangeCmd(
|
||||
ctx,
|
||||
backupGetter,
|
||||
"backup-ID",
|
||||
utils.ExchangeOpts{},
|
||||
)
|
||||
assert.Error(t, err)
|
||||
|
||||
assert.Empty(t, output)
|
||||
}
|
||||
|
||||
// TODO(ashmrtn): Uncomment these when the CLI validates flag input values.
|
||||
//func (suite *ExchangeSuite) TestExchangeBackupDetailsSelectorsBadFormats() {
|
||||
// ctx := context.Background()
|
||||
//
|
||||
// for _, test := range testdata.BadExchangeOptionsFormats {
|
||||
// suite.T().Run(test.Name, func(t *testing.T) {
|
||||
// output, err := runDetailsExchangeCmd(
|
||||
// ctx,
|
||||
// test.BackupGetter,
|
||||
// "backup-ID",
|
||||
// test.Opts,
|
||||
// )
|
||||
// assert.Error(t, err)
|
||||
//
|
||||
// assert.Empty(t, output)
|
||||
// })
|
||||
// }
|
||||
//}
|
||||
|
||||
181
src/cli/utils/testdata/opts.go
vendored
Normal file
181
src/cli/utils/testdata/opts.go
vendored
Normal file
@ -0,0 +1,181 @@
|
||||
package testdata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/alcionai/corso/src/cli/utils"
|
||||
"github.com/alcionai/corso/src/internal/common"
|
||||
"github.com/alcionai/corso/src/internal/model"
|
||||
"github.com/alcionai/corso/src/pkg/backup"
|
||||
"github.com/alcionai/corso/src/pkg/backup/details"
|
||||
"github.com/alcionai/corso/src/pkg/selectors"
|
||||
"github.com/alcionai/corso/src/pkg/selectors/testdata"
|
||||
)
|
||||
|
||||
type ExchangeOptionsTest struct {
|
||||
Name string
|
||||
Opts utils.ExchangeOpts
|
||||
BackupGetter *MockBackupGetter
|
||||
Expected []details.DetailsEntry
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
// BadExchangeOptionsFormats contains ExchangeOpts with flags that should
|
||||
// cause errors about the format of the input flag. Mocks are configured to
|
||||
// allow the system to run if it doesn't throw an error on formatting.
|
||||
BadExchangeOptionsFormats = []ExchangeOptionsTest{
|
||||
{
|
||||
Name: "BadEmailReceiveAfter",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailReceivedAfter: "foo",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "BadEmailReceiveBefore",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailReceivedBefore: "foo",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "BadEventRecurs",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EventRecurs: "foo",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "BadEventStartsAfter",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EventStartsAfter: "foo",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "BadEventStartsBefore",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EventStartsBefore: "foo",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// ExchangeOptionDetailLookups contains flag inputs and expected results for
|
||||
// some choice input patterns. This set is not exhaustive. All inputs and
|
||||
// outputs are according to the data laid out in selectors/testdata. Mocks are
|
||||
// configured to return the full dataset listed in selectors/testdata.
|
||||
ExchangeOptionDetailLookups = []ExchangeOptionsTest{
|
||||
{
|
||||
Name: "Emails",
|
||||
Expected: testdata.ExchangeEmailItems,
|
||||
Opts: utils.ExchangeOpts{
|
||||
Emails: selectors.Any(),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EmailsBySubject",
|
||||
Expected: testdata.ExchangeEmailItems,
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailSender: "a-person",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "AllExchange",
|
||||
Expected: append(
|
||||
append(
|
||||
append(
|
||||
[]details.DetailsEntry{},
|
||||
testdata.ExchangeEmailItems...,
|
||||
),
|
||||
testdata.ExchangeContactsItems...,
|
||||
),
|
||||
testdata.ExchangeEventsItems...,
|
||||
),
|
||||
},
|
||||
{
|
||||
Name: "MailReceivedTime",
|
||||
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailReceivedBefore: common.FormatTime(testdata.Time1.Add(time.Second)),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "MailID",
|
||||
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
||||
Opts: utils.ExchangeOpts{
|
||||
Emails: []string{testdata.ExchangeEmailItemPath1.Item()},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "MailShortRef",
|
||||
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
||||
Opts: utils.ExchangeOpts{
|
||||
Emails: []string{testdata.ExchangeEmailItemPath1.ShortRef()},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "MultipleMailShortRef",
|
||||
Expected: testdata.ExchangeEmailItems,
|
||||
Opts: utils.ExchangeOpts{
|
||||
Emails: []string{
|
||||
testdata.ExchangeEmailItemPath1.ShortRef(),
|
||||
testdata.ExchangeEmailItemPath2.ShortRef(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "AllEventsAndMailWithSubject",
|
||||
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailSubject: "foo",
|
||||
Events: selectors.Any(),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EventsAndMailWithSubject",
|
||||
Expected: []details.DetailsEntry{},
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailSubject: "foo",
|
||||
EventSubject: "foo",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EventsAndMailByShortRef",
|
||||
Expected: []details.DetailsEntry{
|
||||
testdata.ExchangeEmailItems[0],
|
||||
testdata.ExchangeEventsItems[0],
|
||||
},
|
||||
Opts: utils.ExchangeOpts{
|
||||
Emails: []string{testdata.ExchangeEmailItemPath1.ShortRef()},
|
||||
Events: []string{testdata.ExchangeEventsItemPath1.ShortRef()},
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// MockBackupGetter implements the repo.BackupGetter interface and returns
|
||||
// (selectors/testdata.GetDetailsSet(), nil, nil) when BackupDetails is called
|
||||
// on the nil instance. If an instance is given or Backups is called returns an
|
||||
// error.
|
||||
type MockBackupGetter struct{}
|
||||
|
||||
func (MockBackupGetter) Backup(
|
||||
context.Context,
|
||||
model.StableID,
|
||||
) (*backup.Backup, error) {
|
||||
return nil, errors.New("unexpected call to mock")
|
||||
}
|
||||
|
||||
func (MockBackupGetter) Backups(context.Context) ([]backup.Backup, error) {
|
||||
return nil, errors.New("unexpected call to mock")
|
||||
}
|
||||
|
||||
func (bg *MockBackupGetter) BackupDetails(
|
||||
ctx context.Context,
|
||||
backupID string,
|
||||
) (*details.Details, *backup.Backup, error) {
|
||||
if bg == nil {
|
||||
return testdata.GetDetailsSet(), nil, nil
|
||||
}
|
||||
|
||||
return nil, nil, errors.New("unexpected call to mock")
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user