Add path constructor that takes a category (#743)

## Description

Will be useful for parts of graph connector code that are abstracted to
take a category and return collections. Does not work for exchange
events or contacts yet as those paths haven't been defined.

## Type of change

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

## Issue(s)
<!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. -->

part of:
* #671 
* #456 

## Test Plan

<!-- How will this be tested prior to merging.-->

- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2022-09-02 13:18:05 -07:00 committed by GitHub
parent 12f61dd71c
commit 897a21ef0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 11 deletions

View File

@ -198,6 +198,23 @@ func (pb Builder) ToDataLayerExchangeMailPath(tenant, user string, isItem bool)
}, nil
}
func (pb Builder) ToDataLayerExchangePathForCategory(
tenant, user string,
category CategoryType,
isItem bool,
) (Path, error) {
if err := validateServiceAndCategory(ExchangeService, category); err != nil {
return nil, err
}
switch category {
case EmailCategory:
return pb.ToDataLayerExchangeMailPath(tenant, user, isItem)
default:
return nil, errors.New("not implemented")
}
}
// FromDataLayerPath parses the escaped path p, validates the elements in p
// match a resource-specific path format, and returns a Path struct for that
// resource-specific type. If p does not match any resource-specific paths or
@ -219,7 +236,7 @@ func FromDataLayerPath(p string, isItem bool) (Path, error) {
return nil, errors.Errorf("path has too few segments: %s", p)
}
service, category, err := validateServiceAndCategory(
service, category, err := validateServiceAndCategoryStrings(
pb.elements[1],
pb.elements[3],
)

View File

@ -4,8 +4,6 @@ import (
"github.com/pkg/errors"
)
const unknownServiceCombination = "unknown service/category combination %q/%q"
type ServiceType int
//go:generate stringer -type=ServiceType -linecomment
@ -55,29 +53,39 @@ var serviceCategories = map[ServiceType]map[CategoryType]struct{}{
},
}
func validateServiceAndCategory(s, c string) (ServiceType, CategoryType, error) {
// Validity of service checked on first-level lookup to serviceCategories.
func validateServiceAndCategoryStrings(s, c string) (ServiceType, CategoryType, error) {
service := toServiceType(s)
if service == UnknownService {
return UnknownService, UnknownCategory, errors.Errorf("unknown service string %q", s)
}
category := ToCategoryType(c)
if category == UnknownCategory {
return UnknownService, UnknownCategory, errors.Errorf("unknown category string %q", c)
}
if err := validateServiceAndCategory(service, category); err != nil {
return UnknownService, UnknownCategory, err
}
return service, category, nil
}
func validateServiceAndCategory(service ServiceType, category CategoryType) error {
cats, ok := serviceCategories[service]
if !ok {
return UnknownService, UnknownCategory, errors.Errorf("unknown service string %q", s)
return errors.New("unsupported service")
}
if _, ok := cats[category]; !ok {
return UnknownService, UnknownCategory, errors.Errorf(
unknownServiceCombination,
return errors.Errorf(
"unknown service/category combination %q/%q",
service,
category,
)
}
return service, category, nil
return nil
}
// dataLayerResourcePath allows callers to extract information from a

View File

@ -122,6 +122,54 @@ func (suite *PopulatedDataLayerResourcePath) SetupSuite() {
suite.b = path.Builder{}.Append(rest...)
}
func (suite *PopulatedDataLayerResourcePath) TestToExchangeMailPathForCategory() {
table := []struct {
category path.CategoryType
check assert.ErrorAssertionFunc
}{
{
category: path.UnknownCategory,
check: assert.Error,
},
{
category: path.CategoryType(-1),
check: assert.Error,
},
{
category: path.EmailCategory,
check: assert.NoError,
},
}
for _, m := range modes {
suite.T().Run(m.name, func(t1 *testing.T) {
for _, test := range table {
t1.Run(test.category.String(), func(t *testing.T) {
p, err := suite.b.ToDataLayerExchangePathForCategory(
testTenant,
testUser,
test.category,
m.isItem,
)
test.check(t, err)
if err != nil {
return
}
assert.Equal(t, testTenant, p.Tenant())
assert.Equal(t, path.ExchangeService, p.Service())
assert.Equal(t, test.category, p.Category())
assert.Equal(t, testUser, p.ResourceOwner())
assert.Equal(t, m.expectedFolder, p.Folder())
assert.Equal(t, m.expectedItem, p.Item())
})
}
})
}
}
func (suite *PopulatedDataLayerResourcePath) TestTenant() {
for _, m := range modes {
suite.T().Run(m.name, func(t *testing.T) {

View File

@ -34,7 +34,7 @@ func (suite *ServiceCategoryUnitSuite) TestValidateServiceAndCategoryBadStringEr
}
for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) {
_, _, err := validateServiceAndCategory(test.service, test.category)
_, _, err := validateServiceAndCategoryStrings(test.service, test.category)
assert.Error(suite.T(), err)
})
}
@ -100,7 +100,7 @@ func (suite *ServiceCategoryUnitSuite) TestValidateServiceAndCategory() {
}
for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) {
s, c, err := validateServiceAndCategory(test.service, test.category)
s, c, err := validateServiceAndCategoryStrings(test.service, test.category)
test.check(t, err)
if err != nil {