Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NOREF] Initial MTO Milestone resolver tests #1548

Merged
merged 8 commits into from
Dec 4, 2024
172 changes: 172 additions & 0 deletions pkg/graph/resolvers/mto_milestone_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,182 @@
package resolvers

import (
"github.com/samber/lo"

"github.com/cms-enterprise/mint-app/pkg/models"
"github.com/cms-enterprise/mint-app/pkg/storage"
)

// This test ensures that we can properly create a Custom milestone with preset category information
func (suite *ResolverSuite) TestMTOMilestoneCreateCustom() {
// Create model plan
plan := suite.createModelPlan("testing custom milestone creation")

// Make a category and sub category
cat1Name := "Category 1"
cat1SubAName := "Category 1A"
category1, err := MTOCategoryCreate(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, cat1Name, plan.ID, nil)
suite.NoError(err)
category1SubA, err := MTOCategoryCreate(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, cat1SubAName, plan.ID, &category1.ID)
suite.NoError(err)

// Create an uncategorized custom milestone
milestone, err := MTOMilestoneCreateCustom(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, "Custom Milestone", plan.ID, nil)
suite.NoError(err)
suite.Nil(milestone.MTOCategoryID)
suite.Equal(suite.testConfigs.Principal.UserAccount.ID, milestone.CreatedBy)
suite.Nil(milestone.ModifiedBy)
suite.Nil(milestone.ModifiedDts)

// Create a custom milestone under the parent category
milestone1, err := MTOMilestoneCreateCustom(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, "Custom Milestone 1", plan.ID, &category1.ID)
suite.NoError(err)
if suite.NotNil(milestone1.MTOCategoryID) {
suite.Equal(category1.ID, *milestone1.MTOCategoryID)
}
suite.Equal(suite.testConfigs.Principal.UserAccount.ID, milestone1.CreatedBy)
suite.Nil(milestone1.ModifiedBy)
suite.Nil(milestone1.ModifiedDts)

// Create a custom milestone under the subcategory
milestone1A, err := MTOMilestoneCreateCustom(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, "Custom Milestone 1A", plan.ID, &category1SubA.ID)
suite.NoError(err)
if suite.NotNil(milestone1A.MTOCategoryID) {
suite.Equal(category1SubA.ID, *milestone1A.MTOCategoryID)
}
suite.Equal(suite.testConfigs.Principal.UserAccount.ID, milestone1A.CreatedBy)
suite.Nil(milestone1A.ModifiedBy)
suite.Nil(milestone1A.ModifiedDts)
}

// This test ensures that you get an error if you try and create 2 milestones with the same name (regardless of if they're in the same category or not)
func (suite *ResolverSuite) TestMTOMilestoneCreateCustomDuplicates() {
// Create model plan
plan := suite.createModelPlan("testing duplicate custom milestone creation")

// Create an uncategorized custom milestone
milestone, err := MTOMilestoneCreateCustom(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, "Custom Milestone", plan.ID, nil)
suite.NoError(err)
suite.NotNil(milestone)

// Try and create one with the same name
milestoneDupe, err := MTOMilestoneCreateCustom(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, "Custom Milestone", plan.ID, nil)
suite.Error(err)
suite.Nil(milestoneDupe)

// Try and create one with the same even though it's in a different category
category, err := MTOCategoryCreate(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, "Custom Category", plan.ID, nil)
suite.NoError(err)
milestoneDupe, err = MTOMilestoneCreateCustom(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, "Custom Milestone", plan.ID, &category.ID)
suite.Error(err)
suite.Nil(milestoneDupe)
}

// This test checks to see that we can create common milestones and that the appropriate categories are created automatically
func (suite *ResolverSuite) TestMTOMilestoneCreateCommonWithCategories() {
// Create model plan
plan := suite.createModelPlan("testing common milestone creation")

// First, make sure there's no categories to start (except uncategorized)
categories, err := MTOCategoryGetByModelPlanIDLOADER(suite.testConfigs.Context, plan.ID)
suite.NoError(err)
suite.Len(categories, 1) // Just uncategorized

// Then, create a common milestone
milestone, err := MTOMilestoneCreateCommon(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, plan.ID, models.MTOCommonMilestoneKeyManageCd, []models.MTOCommonSolutionKey{})
suite.NoError(err)
suite.Equal(suite.testConfigs.Principal.UserAccount.ID, milestone.CreatedBy)
suite.Nil(milestone.ModifiedBy)
suite.Nil(milestone.ModifiedDts)

// We could potentially validate/check names of Categories on the Milestone object using MTOCategoriesGetByID,
// but we already want to fetch the entire list of categories later to make sure the right number show up,
// and we can just check for the right names to show up while we fetch them.

// Check and see if the categories came along as expected
// You can check which we expect to get created with migrations/V190__Add_Common_Milestone_Library.sql (or future similar migrations that edit the library)
// In this case MTOCommonMilestoneKeyManageCd should create 2 categories (parent, subcategory) of ('Operations','Participant and beneficiary tracking')
categories, err = MTOCategoryGetByModelPlanIDLOADER(suite.testConfigs.Context, plan.ID)
suite.NoError(err)
suite.Len(categories, 2) // 1 new category (Operations) + Uncategorized

operationsCategory, found := lo.Find(categories, func(item *models.MTOCategory) bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the resolver is merged in, I might suggest calling MTOCategoriesGetByID to verify the category and subcategory. I do like that this is validating the category creation though!

Also fine to keep this the way it is since you are validating all categories for the MTO!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll see if I can simplify any of this using this new resolver :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm just going to add a comment for a potential change here -- I had a bit of trouble implementing MTOCategoriesGetByID because I still ended up wanting to fetch the total list of categories/subcategories to ensure the proper number of categories existed post-creation (which MTOCategoriesGetByID doesn't necessarily validate)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return item != nil && item.Name == "Operations"
})
suite.True(found)

operationsSubCategories, err := MTOSubcategoryGetByParentIDLoader(suite.testConfigs.Context, plan.ID, operationsCategory.ID)
suite.NoError(err)
suite.Len(operationsSubCategories, 2) // should have 'Participant and beneficiary tracking' + Uncategorized
participantSubcategory, found := lo.Find(operationsSubCategories, func(item *models.MTOSubcategory) bool {
return item != nil && item.Name == "Participant and beneficiary tracking"
})
suite.True(found)

if suite.NotNil(milestone.MTOCategoryID) {
suite.Equal(participantSubcategory.ID, *milestone.MTOCategoryID) // ensure that the common milestone was created pointed to the subcategory
}

// Finally, do the same, but ensure that if we would try to create a duplicate category by name, we fail silently
// For this example, models.MTOCommonMilestoneKeyAppSupportCon will attempt to create ('Operations','Internal functions'), but since
// the 'Operations' category already exists, we should only see a single new subcategory ('Internal functions')
milestone2, err := MTOMilestoneCreateCommon(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, plan.ID, models.MTOCommonMilestoneKeyAppSupportCon, []models.MTOCommonSolutionKey{})
suite.NoError(err)
suite.Equal(suite.testConfigs.Principal.UserAccount.ID, milestone2.CreatedBy)
suite.Nil(milestone2.ModifiedBy)
suite.Nil(milestone2.ModifiedDts)

// Shouldn't have any new top-level categories, just 'Operations' and 'Uncategorized'
categories, err = MTOCategoryGetByModelPlanIDLOADER(suite.testConfigs.Context, plan.ID)
suite.NoError(err)
suite.Len(categories, 2) // 1 existing category (Operations) + Uncategorized

// Re-fetch subcategories to see if we see 3 total (since we added 'Internal functions')
operationsSubCategories, err = MTOSubcategoryGetByParentIDLoader(suite.testConfigs.Context, plan.ID, operationsCategory.ID)
suite.NoError(err)
suite.Len(operationsSubCategories, 3) // should have 'Participant and beneficiary tracking', 'Internal functions', + Uncategorized

// Find 'Participant and beneficiary tracking'
_, foundParticipant := lo.Find(operationsSubCategories, func(item *models.MTOSubcategory) bool {
return item != nil && item.Name == "Participant and beneficiary tracking"
})
suite.True(foundParticipant)

// Find 'Internal functions'
_, foundInternalFunctions := lo.Find(operationsSubCategories, func(item *models.MTOSubcategory) bool {
return item != nil && item.Name == "Internal functions"
})
suite.True(foundInternalFunctions)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be useful to validate a case where the subcategory already exists? Or that it will make a new category if you rename a category?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might add some TODO comments to consider those cases! I didn't do those right away since I wanted to just kickstart these tests with the happy paths, but I agree these would be good test cases!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

// This test makes sure that you get an error if you try and create 2 milestones sourced from the same common milestone
func (suite *ResolverSuite) TestMTOMilestoneCreateCommonDuplicates() {
// Create model plan
plan := suite.createModelPlan("testing common milestone creation")

// First, create a common milestone
milestone, err := MTOMilestoneCreateCommon(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, plan.ID, models.MTOCommonMilestoneKeyManageCd, []models.MTOCommonSolutionKey{})
suite.NoError(err)
suite.Equal(suite.testConfigs.Principal.UserAccount.ID, milestone.CreatedBy)
suite.Nil(milestone.ModifiedBy)
suite.Nil(milestone.ModifiedDts)

// Then, try to create another with the same Common Milestone key and expect a failure
milestoneDupe, err := MTOMilestoneCreateCommon(suite.testConfigs.Context, suite.testConfigs.Logger, suite.testConfigs.Principal, suite.testConfigs.Store, plan.ID, models.MTOCommonMilestoneKeyManageCd, []models.MTOCommonSolutionKey{})
suite.Error(err)
suite.Nil(milestoneDupe)
}

// TODO We might also want to test deleting a category and making sure it's re-created

// TODO We might also want to test making sure sub-categories also fail silently a category and making sure it's re-created

// TODO (mto) Write tests for MTOMilestoneUpdate

// TODO (mto) Maybe(?) write MTOMilestoneGetByModelPlanIDLOADER

// TODO (mto) Maybe(?) write MTOMilestoneGetByModelPlanIDAndCategoryIDLOADER

func (suite *ResolverSuite) TestCreateMilestoneSolutionLinks() {
plan := suite.createModelPlan("plan for testing MTO create milestone solution links")
commonMilestoneKey := models.MTOCommonMilestoneKeyAppSupportCon
Expand Down
Loading