From 69eef992c54ae740ecad4336be19af5a7d3e7b72 Mon Sep 17 00:00:00 2001 From: Jimmy Vo Date: Thu, 5 Dec 2024 18:06:05 -0500 Subject: [PATCH] Refactor existing tests and add new tests. --- .../org-seat-limit-reached.validator.spec.ts | 107 ++++++++++++++---- 1 file changed, 84 insertions(+), 23 deletions(-) diff --git a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/validators/org-seat-limit-reached.validator.spec.ts b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/validators/org-seat-limit-reached.validator.spec.ts index 000c4467c7f..5157851e52d 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/validators/org-seat-limit-reached.validator.spec.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/validators/org-seat-limit-reached.validator.spec.ts @@ -1,10 +1,14 @@ -import { AbstractControl, FormControl, ValidationErrors } from "@angular/forms"; +import { FormControl } from "@angular/forms"; import { OrganizationUserType } from "@bitwarden/common/admin-console/enums"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { ProductTierType } from "@bitwarden/common/billing/enums"; -import { orgSeatLimitReachedValidator } from "./org-seat-limit-reached.validator"; +import { + orgSeatLimitReachedValidator, + isFixedSeatPlan, + isDynamicSeatPlan, +} from "./org-seat-limit-reached.validator"; const orgFactory = (props: Partial = {}) => Object.assign( @@ -18,19 +22,16 @@ const orgFactory = (props: Partial = {}) => ); describe("orgSeatLimitReachedValidator", () => { - let organization: Organization; - let allOrganizationUserEmails: string[]; - let validatorFn: (control: AbstractControl) => ValidationErrors | null; - - beforeEach(() => { - allOrganizationUserEmails = ["user1@example.com"]; - }); + const allOrganizationUserEmails = ["user1@example.com"]; + const dummyOrg: Organization = null; + const dummyOccupiedSeatCount = 1; it("should return null when control value is empty", () => { - validatorFn = orgSeatLimitReachedValidator( - organization, + const validatorFn = orgSeatLimitReachedValidator( + dummyOrg, allOrganizationUserEmails, "You cannot invite more than 2 members without upgrading your plan.", + dummyOccupiedSeatCount, ); const control = new FormControl(""); @@ -40,10 +41,11 @@ describe("orgSeatLimitReachedValidator", () => { }); it("should return null when control value is null", () => { - validatorFn = orgSeatLimitReachedValidator( - organization, + const validatorFn = orgSeatLimitReachedValidator( + dummyOrg, allOrganizationUserEmails, "You cannot invite more than 2 members without upgrading your plan.", + dummyOccupiedSeatCount, ); const control = new FormControl(null); @@ -53,14 +55,18 @@ describe("orgSeatLimitReachedValidator", () => { }); it("should return null when max seats are not exceeded on free plan", () => { - organization = orgFactory({ + const organization = orgFactory({ productTierType: ProductTierType.Free, seats: 2, }); - validatorFn = orgSeatLimitReachedValidator( + + const OccupiedSeatCount = 1; + + const validatorFn = orgSeatLimitReachedValidator( organization, allOrganizationUserEmails, "You cannot invite more than 2 members without upgrading your plan.", + OccupiedSeatCount, ); const control = new FormControl("user2@example.com"); @@ -70,15 +76,20 @@ describe("orgSeatLimitReachedValidator", () => { }); it("should return null when max seats are not exceeded on teams starter plan", () => { - organization = orgFactory({ + const organization = orgFactory({ productTierType: ProductTierType.TeamsStarter, seats: 10, }); - validatorFn = orgSeatLimitReachedValidator( + + const occupiedSeatCount = 0; + + const validatorFn = orgSeatLimitReachedValidator( organization, allOrganizationUserEmails, "You cannot invite more than 10 members without upgrading your plan.", + occupiedSeatCount, ); + const control = new FormControl( "user2@example.com," + "user3@example.com," + @@ -97,7 +108,7 @@ describe("orgSeatLimitReachedValidator", () => { }); it("should return validation error when max seats are exceeded on free plan", () => { - organization = orgFactory({ + const organization = orgFactory({ productTierType: ProductTierType.Free, seats: 2, }); @@ -105,7 +116,7 @@ describe("orgSeatLimitReachedValidator", () => { const occupiedSeatCount = 1; - validatorFn = orgSeatLimitReachedValidator( + const validatorFn = orgSeatLimitReachedValidator( organization, allOrganizationUserEmails, "You cannot invite more than 2 members without upgrading your plan.", @@ -118,16 +129,40 @@ describe("orgSeatLimitReachedValidator", () => { expect(result).toStrictEqual({ seatLimitReached: { message: errorMessage } }); }); - it("should return null when not on free plan", () => { + it("should return null when on dynamic seat plan", () => { const control = new FormControl("user2@example.com,user3@example.com"); - organization = orgFactory({ + const organization = orgFactory({ productTierType: ProductTierType.Enterprise, seats: 100, }); - validatorFn = orgSeatLimitReachedValidator( + + const validatorFn = orgSeatLimitReachedValidator( organization, allOrganizationUserEmails, - "You cannot invite more than 2 members without upgrading your plan.", + "Enterprise plan dummy error.", + dummyOccupiedSeatCount, + ); + + const result = validatorFn(control); + + expect(result).toBeNull(); + }); + + it("should only count unique input email addresses", () => { + const control = new FormControl( + "sameUser1@example.com,sameUser1@example.com,user2@example.com,user3@example.com", + ); + const organization = orgFactory({ + productTierType: ProductTierType.Families, + seats: 6, + }); + + const occupiedSeatCount = 3; + const validatorFn = orgSeatLimitReachedValidator( + organization, + allOrganizationUserEmails, + "Family plan dummy error.", + occupiedSeatCount, ); const result = validatorFn(control); @@ -135,3 +170,29 @@ describe("orgSeatLimitReachedValidator", () => { expect(result).toBeNull(); }); }); + +describe("isFixedSeatPlan", () => { + test.each([ + [ProductTierType.Free, true], + [ProductTierType.Families, true], + [ProductTierType.TeamsStarter, true], + [ProductTierType.Enterprise, false], + [null, false], + [undefined, false], + ])("should return %s for %s", (input, expected) => { + expect(isFixedSeatPlan(input as ProductTierType)).toBe(expected); + }); +}); + +describe("isDynamicSeatPlan", () => { + test.each([ + [ProductTierType.Enterprise, true], + [ProductTierType.Free, false], + [ProductTierType.Families, false], + [ProductTierType.TeamsStarter, false], + [null, false], + [undefined, false], + ])("should return %s for %s", (input, expected) => { + expect(isDynamicSeatPlan(input as ProductTierType)).toBe(expected); + }); +});