diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/SentryPlanController/SentryPlanController.test.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/SentryPlanController/SentryPlanController.test.tsx
index 72ccfd7bb0..2d48891335 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/SentryPlanController/SentryPlanController.test.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/SentryPlanController/SentryPlanController.test.tsx
@@ -26,7 +26,7 @@ vi.mock('@stripe/react-stripe-js')
const basicPlan = {
marketingName: 'Basic',
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
billingRate: null,
baseUnitPrice: 0,
benefits: [
@@ -39,7 +39,7 @@ const basicPlan = {
const sentryPlanMonth = {
marketingName: 'Sentry Pro',
- value: 'users-sentrym',
+ value: Plans.USERS_SENTRYM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -55,7 +55,7 @@ const sentryPlanMonth = {
const sentryPlanYear = {
marketingName: 'Sentry Pro',
- value: 'users-sentryy',
+ value: Plans.USERS_SENTRYY,
billingRate: 'annually',
baseUnitPrice: 10,
benefits: [
@@ -106,7 +106,7 @@ const mockPlanDataResponseMonthly = {
billingRate: 'monthly',
marketingName: 'Pro',
monthlyUploadLimit: 2500,
- value: 'test-plan',
+ value: Plans.USERS_SENTRYM,
trialStatus: TrialStatuses.NOT_STARTED,
trialStartDate: '',
trialEndDate: '',
@@ -122,7 +122,7 @@ const mockPlanDataResponseYearly = {
billingRate: 'yearly',
marketingName: 'Pro',
monthlyUploadLimit: 2500,
- value: 'test-plan',
+ value: Plans.USERS_SENTRYY,
trialStatus: TrialStatuses.NOT_STARTED,
trialStartDate: '',
trialEndDate: '',
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/SentryPlanController/SentryPlanController.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/SentryPlanController/SentryPlanController.tsx
index beced2ec1f..91a7a1be81 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/SentryPlanController/SentryPlanController.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/SentryPlanController/SentryPlanController.tsx
@@ -1,5 +1,6 @@
import { UseFormRegister, UseFormSetValue } from 'react-hook-form'
+import { PlanName } from 'shared/utils/billing'
import { MIN_SENTRY_SEATS } from 'shared/utils/upgradeForm'
import TextInput from 'ui/TextInput'
@@ -7,12 +8,11 @@ import BillingOptions from './BillingOptions'
import PriceCallout from './PriceCallout'
import UserCount from './UserCount'
-import { NewPlanType } from '../../constants'
import { UpgradeFormFields } from '../../UpgradeForm'
interface SentryPlanControllerProps {
seats: number
- newPlan: NewPlanType
+ newPlan?: PlanName
register: UseFormRegister
setFormValue: UseFormSetValue
errors?: {
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/BillingOptions/BillingOptions.test.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/BillingOptions/BillingOptions.test.tsx
index 0dd2fec4e2..0de7ffb3e7 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/BillingOptions/BillingOptions.test.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/BillingOptions/BillingOptions.test.tsx
@@ -14,7 +14,7 @@ import BillingOptions from './BillingOptions'
const availablePlans = [
{
marketingName: 'Basic',
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
billingRate: null,
baseUnitPrice: 0,
benefits: [
@@ -30,7 +30,7 @@ const availablePlans = [
billingRate: 'monthly',
marketingName: 'Team',
monthlyUploadLimit: 2500,
- value: 'users-teamm',
+ value: Plans.USERS_TEAMM,
},
{
baseUnitPrice: 4,
@@ -38,7 +38,7 @@ const availablePlans = [
billingRate: 'annually',
marketingName: 'Team',
monthlyUploadLimit: 2500,
- value: 'users-teamy',
+ value: Plans.USERS_TEAMY,
},
]
@@ -48,7 +48,7 @@ const mockPlanDataResponse = {
billingRate: 'monthly',
marketingName: 'Team',
monthlyUploadLimit: 250,
- value: 'test-plan',
+ value: Plans.USERS_TEAMM,
trialStatus: TrialStatuses.NOT_STARTED,
trialStartDate: '',
trialEndDate: '',
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/BillingOptions/BillingOptions.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/BillingOptions/BillingOptions.tsx
index 26a959e872..37650ff613 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/BillingOptions/BillingOptions.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/BillingOptions/BillingOptions.tsx
@@ -7,15 +7,16 @@ import {
findTeamPlans,
isAnnualPlan,
isMonthlyPlan,
+ PlanName,
Plans,
} from 'shared/utils/billing'
import OptionButton from 'ui/OptionButton'
-import { NewPlanType, OptionPeriod, TimePeriods } from '../../../constants'
+import { OptionPeriod, TimePeriods } from '../../../constants'
import { UpgradeFormFields } from '../../../UpgradeForm'
interface BillingControlsProps {
- newPlan: NewPlanType
+ newPlan?: PlanName
setFormValue: UseFormSetValue
}
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/ErrorBanner/ErrorBanner.test.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/ErrorBanner/ErrorBanner.test.tsx
index 4d491832e5..1e9e6de888 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/ErrorBanner/ErrorBanner.test.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/ErrorBanner/ErrorBanner.test.tsx
@@ -14,7 +14,7 @@ import ErrorBanner from './ErrorBanner'
const basicPlan = {
marketingName: 'Basic',
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
billingRate: null,
baseUnitPrice: 0,
benefits: [
@@ -31,7 +31,7 @@ const teamPlanMonth = {
billingRate: 'monthly',
marketingName: 'Users Team',
monthlyUploadLimit: 2500,
- value: 'users-teamm',
+ value: Plans.USERS_TEAMM,
quantity: 10,
}
@@ -41,7 +41,7 @@ const teamPlanYear = {
billingRate: 'annually',
marketingName: 'Users Team',
monthlyUploadLimit: 2500,
- value: 'users-teamy',
+ value: Plans.USERS_TEAMY,
quantity: 5,
}
@@ -93,7 +93,7 @@ const mockPlanDataResponseMonthly = {
billingRate: 'monthly',
marketingName: 'Pro Team',
monthlyUploadLimit: 2500,
- value: 'test-plan',
+ value: Plans.USERS_TEAMM,
trialStatus: TrialStatuses.NOT_STARTED,
trialStartDate: '',
trialEndDate: '',
@@ -108,7 +108,7 @@ const mockPlanDataResponseYearly = {
billingRate: 'yearly',
marketingName: 'Pro Team',
monthlyUploadLimit: 2500,
- value: 'test-plan',
+ value: Plans.USERS_TEAMM,
trialStatus: TrialStatuses.NOT_STARTED,
trialStartDate: '',
trialEndDate: '',
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/ErrorBanner/ErrorBanner.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/ErrorBanner/ErrorBanner.tsx
index 7cfc8a6a2f..473250cda3 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/ErrorBanner/ErrorBanner.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/ErrorBanner/ErrorBanner.tsx
@@ -1,15 +1,12 @@
import { UseFormSetValue } from 'react-hook-form'
import { useParams } from 'react-router-dom'
-import {
- IndividualPlan,
- useAccountDetails,
- useAvailablePlans,
-} from 'services/account'
+import { useAccountDetails, useAvailablePlans } from 'services/account'
import {
canApplySentryUpgrade,
findProPlans,
findSentryPlans,
+ Plan,
} from 'shared/utils/billing'
import { UPGRADE_FORM_TOO_MANY_SEATS_MESSAGE } from 'shared/utils/upgradeForm'
@@ -24,7 +21,7 @@ interface Errors {
interface ErrorBannerProps {
errors: Errors
setFormValue: UseFormSetValue
- setSelectedPlan: (plan: IndividualPlan) => void
+ setSelectedPlan: (plan?: Plan) => void
}
export default function ErrorBanner({
@@ -37,7 +34,8 @@ export default function ErrorBanner({
const { data: accountDetails } = useAccountDetails({ provider, owner })
const { proPlanYear } = findProPlans({ plans })
const { sentryPlanYear } = findSentryPlans({ plans })
- const plan = accountDetails?.rootOrganization?.plan ?? accountDetails?.plan
+ const plan =
+ accountDetails?.rootOrganization?.plan?.value ?? accountDetails?.plan?.value
const isSentryUpgrade = canApplySentryUpgrade({ plan, plans })
const yearlyProPlan = isSentryUpgrade ? sentryPlanYear : proPlanYear
@@ -52,7 +50,7 @@ export default function ErrorBanner({
className="cursor-pointer font-semibold text-ds-blue-darker hover:underline"
onClick={() => {
setSelectedPlan(yearlyProPlan)
- setFormValue('newPlan', yearlyProPlan.value, {
+ setFormValue('newPlan', yearlyProPlan?.value, {
shouldValidate: true,
})
}}
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/PriceCallout/PriceCallout.test.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/PriceCallout/PriceCallout.test.tsx
index c3936d9cba..3d4de3e232 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/PriceCallout/PriceCallout.test.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/PriceCallout/PriceCallout.test.tsx
@@ -13,7 +13,7 @@ import PriceCallout from './PriceCallout'
const availablePlans = [
{
marketingName: 'Basic',
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
billingRate: null,
baseUnitPrice: 0,
benefits: [
@@ -25,7 +25,7 @@ const availablePlans = [
},
{
marketingName: 'Pro',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -38,7 +38,7 @@ const availablePlans = [
},
{
marketingName: 'Team',
- value: 'users-teamm',
+ value: Plans.USERS_TEAMM,
billingRate: 'monthly',
baseUnitPrice: 5,
benefits: ['Patch coverage analysis'],
@@ -46,7 +46,7 @@ const availablePlans = [
},
{
marketingName: 'Team',
- value: 'users-teamy',
+ value: Plans.USERS_TEAMY,
billingRate: 'yearly',
baseUnitPrice: 4,
benefits: ['Patch coverage analysis'],
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/PriceCallout/PriceCallout.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/PriceCallout/PriceCallout.tsx
index 943cf0d074..7967343499 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/PriceCallout/PriceCallout.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/PriceCallout/PriceCallout.tsx
@@ -9,6 +9,7 @@ import {
formatNumberToUSD,
getNextBillingDate,
isAnnualPlan,
+ PlanName,
Plans,
} from 'shared/utils/billing'
import {
@@ -18,11 +19,10 @@ import {
} from 'shared/utils/upgradeForm'
import Icon from 'ui/Icon'
-import { NewPlanType } from '../../../constants'
import { UpgradeFormFields } from '../../../UpgradeForm'
interface PriceCalloutProps {
- newPlan: NewPlanType
+ newPlan?: PlanName
seats: number
setFormValue: UseFormSetValue
}
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/TeamPlanController.test.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/TeamPlanController.test.tsx
index cf8cb10b71..baaeb7ef6a 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/TeamPlanController.test.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/TeamPlanController.test.tsx
@@ -28,7 +28,7 @@ vi.mock('@stripe/react-stripe-js')
const basicPlan = {
marketingName: 'Basic',
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
billingRate: null,
baseUnitPrice: 0,
benefits: [
@@ -45,7 +45,7 @@ const teamPlanMonth = {
billingRate: 'monthly',
marketingName: 'Users Team',
monthlyUploadLimit: 2500,
- value: 'users-teamm',
+ value: Plans.USERS_TEAMM,
quantity: 10,
}
@@ -55,7 +55,7 @@ const teamPlanYear = {
billingRate: 'annually',
marketingName: 'Users Team',
monthlyUploadLimit: 2500,
- value: 'users-teamy',
+ value: Plans.USERS_TEAMY,
quantity: 5,
}
@@ -107,7 +107,7 @@ const mockPlanDataResponseMonthly = {
billingRate: 'monthly',
marketingName: 'Pro Team',
monthlyUploadLimit: 2500,
- value: 'test-plan',
+ value: Plans.USERS_PR_INAPPM,
trialStatus: TrialStatuses.NOT_STARTED,
trialStartDate: '',
trialEndDate: '',
@@ -123,7 +123,7 @@ const mockPlanDataResponseYearly = {
billingRate: 'yearly',
marketingName: 'Pro Team',
monthlyUploadLimit: 2500,
- value: 'test-plan',
+ value: Plans.USERS_PR_INAPPY,
trialStatus: TrialStatuses.NOT_STARTED,
trialStartDate: '',
trialEndDate: '',
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/TeamPlanController.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/TeamPlanController.tsx
index 972d55e779..c7d3b97948 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/TeamPlanController.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/Controllers/TeamPlanController/TeamPlanController.tsx
@@ -1,6 +1,6 @@
import { UseFormRegister, UseFormSetValue } from 'react-hook-form'
-import { IndividualPlan } from 'services/account'
+import { Plan, PlanName } from 'shared/utils/billing'
import {
MIN_NB_SEATS_PRO,
TEAM_PLAN_MAX_ACTIVE_USERS,
@@ -12,7 +12,6 @@ import ErrorBanner from './ErrorBanner'
import PriceCallout from './PriceCallout'
import UserCount from './UserCount'
-import { NewPlanType } from '../../constants'
import { UpgradeFormFields } from '../../UpgradeForm'
interface Errors {
@@ -23,10 +22,10 @@ interface Errors {
interface PlanControllerProps {
seats: number
- newPlan: NewPlanType
+ newPlan?: PlanName
register: UseFormRegister
setFormValue: UseFormSetValue
- setSelectedPlan: (plan: IndividualPlan) => void
+ setSelectedPlan: (plan?: Plan) => void
errors?: Errors
}
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/PlanTypeOptions/PlanTypeOptions.test.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/PlanTypeOptions/PlanTypeOptions.test.tsx
index fc476c765d..0e02d3a6be 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/PlanTypeOptions/PlanTypeOptions.test.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/PlanTypeOptions/PlanTypeOptions.test.tsx
@@ -7,13 +7,13 @@ import qs from 'qs'
import { Suspense } from 'react'
import { MemoryRouter, Route, useLocation } from 'react-router-dom'
-import { Plans } from 'shared/utils/billing'
+import { PlanName, Plans } from 'shared/utils/billing'
import PlanTypeOptions from './PlanTypeOptions'
const basicPlan = {
marketingName: 'Basic',
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
billingRate: null,
baseUnitPrice: 0,
benefits: [
@@ -26,7 +26,7 @@ const basicPlan = {
const proPlanMonth = {
marketingName: 'Pro Team',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -40,7 +40,7 @@ const proPlanMonth = {
const proPlanYear = {
marketingName: 'Pro Team',
- value: 'users-pr-inappy',
+ value: Plans.USERS_PR_INAPPY,
billingRate: 'annually',
baseUnitPrice: 10,
benefits: [
@@ -54,7 +54,7 @@ const proPlanYear = {
const sentryPlanMonth = {
marketingName: 'Sentry Pro Team',
- value: 'users-sentrym',
+ value: Plans.USERS_SENTRYM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -68,7 +68,7 @@ const sentryPlanMonth = {
const sentryPlanYear = {
marketingName: 'Sentry Pro Team',
- value: 'users-sentryy',
+ value: Plans.USERS_SENTRYY,
billingRate: 'annually',
baseUnitPrice: 10,
benefits: [
@@ -86,7 +86,7 @@ const teamPlanMonth = {
billingRate: 'monthly',
marketingName: 'Users Team',
monthlyUploadLimit: 2500,
- value: 'users-teamm',
+ value: Plans.USERS_TEAMM,
}
const teamPlanYear = {
@@ -95,12 +95,12 @@ const teamPlanYear = {
billingRate: 'annually',
marketingName: 'Users Team',
monthlyUploadLimit: 2500,
- value: 'users-teamy',
+ value: Plans.USERS_TEAMY,
}
const trialPlan = {
marketingName: 'Pro Trial Team',
- value: 'users-trial',
+ value: Plans.USERS_TRIAL,
billingRate: null,
baseUnitPrice: 12,
benefits: ['Configurable # of users', 'Unlimited repos'],
@@ -182,7 +182,7 @@ const mockAccountDetailsTrial = {
}
type SetupArgs = {
- planValue: string
+ planValue: PlanName
hasSentryPlans: boolean
hasTeamPlans: boolean
}
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/PlanTypeOptions/PlanTypeOptions.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/PlanTypeOptions/PlanTypeOptions.tsx
index 51bd452650..bd404e0488 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/PlanTypeOptions/PlanTypeOptions.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/PlanTypeOptions/PlanTypeOptions.tsx
@@ -1,11 +1,7 @@
import { UseFormSetValue } from 'react-hook-form'
import { useParams } from 'react-router-dom'
-import {
- IndividualPlan,
- useAccountDetails,
- useAvailablePlans,
-} from 'services/account'
+import { useAccountDetails, useAvailablePlans } from 'services/account'
import { useLocationParams } from 'services/navigation'
import { TierNames } from 'services/tier'
import {
@@ -15,6 +11,8 @@ import {
findTeamPlans,
isMonthlyPlan,
isTeamPlan,
+ Plan,
+ PlanName,
shouldDisplayTeamCard,
} from 'shared/utils/billing'
import { TEAM_PLAN_MAX_ACTIVE_USERS } from 'shared/utils/upgradeForm'
@@ -26,8 +24,8 @@ import { UpgradeFormFields } from '../UpgradeForm'
interface PlanTypeOptionsProps {
setFormValue: UseFormSetValue
- setSelectedPlan: (x: IndividualPlan) => void
- newPlan: string
+ setSelectedPlan: (x?: Plan) => void
+ newPlan?: PlanName
}
const PlanTypeOptions: React.FC = ({
@@ -47,7 +45,8 @@ const PlanTypeOptions: React.FC = ({
})
const hasTeamPlans = shouldDisplayTeamCard({ plans })
- const plan = accountDetails?.rootOrganization?.plan ?? accountDetails?.plan
+ const plan =
+ accountDetails?.rootOrganization?.plan?.value ?? accountDetails?.plan?.value
const isSentryUpgrade = canApplySentryUpgrade({ plan, plans })
const yearlyProPlan = isSentryUpgrade ? sentryPlanYear : proPlanYear
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpdateBlurb/UpdateBlurb.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpdateBlurb/UpdateBlurb.tsx
index 99cdfcbc6e..df0e440cdd 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpdateBlurb/UpdateBlurb.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpdateBlurb/UpdateBlurb.tsx
@@ -1,9 +1,12 @@
import { z } from 'zod'
import { PlanSchema } from 'services/account'
-import { isAnnualPlan, isFreePlan, isTeamPlan } from 'shared/utils/billing'
-
-import { NewPlanType } from '../constants'
+import {
+ isAnnualPlan,
+ isFreePlan,
+ isTeamPlan,
+ PlanName,
+} from 'shared/utils/billing'
const UpdateBlurb = ({
currentPlan,
@@ -14,7 +17,7 @@ const UpdateBlurb = ({
}: {
currentPlan?: z.infer
selectedPlan?: z.infer
- newPlanName: NewPlanType
+ newPlanName?: PlanName
seats: number
nextBillingDate: string
}) => {
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpdateButton/UpdateButton.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpdateButton/UpdateButton.tsx
index 8795c664b4..c3dd67e899 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpdateButton/UpdateButton.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpdateButton/UpdateButton.tsx
@@ -2,15 +2,13 @@ import React from 'react'
import { useParams } from 'react-router-dom'
import { useAccountDetails } from 'services/account'
-import { isFreePlan } from 'shared/utils/billing'
+import { isFreePlan, PlanName } from 'shared/utils/billing'
import Button from 'ui/Button'
-import { NewPlanType } from '../constants'
-
interface BillingControlsProps {
seats: number
isValid: boolean
- newPlan: NewPlanType
+ newPlan?: PlanName
}
const UpdateButton: React.FC = ({
@@ -21,7 +19,7 @@ const UpdateButton: React.FC = ({
const { provider, owner } = useParams<{ provider: string; owner: string }>()
const { data: accountDetails } = useAccountDetails({ provider, owner })
- const currentPlanValue = accountDetails?.plan?.value || '0'
+ const currentPlanValue = accountDetails?.plan?.value
const currentPlanQuantity = accountDetails?.plan?.quantity || 0
const isSamePlan = newPlan === currentPlanValue
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpgradeForm.test.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpgradeForm.test.tsx
index 1efdd06797..45d2e808d4 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpgradeForm.test.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpgradeForm.test.tsx
@@ -6,9 +6,9 @@ import { setupServer } from 'msw/node'
import { Suspense } from 'react'
import { MemoryRouter, Route, useLocation } from 'react-router-dom'
-import { IndividualPlan, TrialStatuses } from 'services/account'
+import { TrialStatuses } from 'services/account'
import { accountDetailsParsedObj } from 'services/account/mocks'
-import { Plans } from 'shared/utils/billing'
+import { Plan, Plans } from 'shared/utils/billing'
import UpgradeForm from './UpgradeForm'
@@ -29,7 +29,7 @@ vi.mock('@sentry/react')
const basicPlan = {
marketingName: 'Basic',
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
billingRate: null,
baseUnitPrice: 0,
benefits: [
@@ -72,7 +72,7 @@ const proPlanYear = {
const sentryPlanMonth = {
marketingName: 'Sentry Pro Team',
- value: 'users-sentrym',
+ value: Plans.USERS_SENTRYM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -88,7 +88,7 @@ const sentryPlanMonth = {
const sentryPlanYear = {
marketingName: 'Sentry Pro Team',
- value: 'users-sentryy',
+ value: Plans.USERS_SENTRYY,
billingRate: 'annually',
baseUnitPrice: 10,
benefits: [
@@ -108,7 +108,7 @@ const teamPlanMonth = {
billingRate: 'monthly',
marketingName: 'Users Team',
monthlyUploadLimit: 2500,
- value: 'users-teamm',
+ value: Plans.USERS_TEAMM,
}
const teamPlanYear = {
@@ -117,12 +117,12 @@ const teamPlanYear = {
billingRate: 'annually',
marketingName: 'Users Team',
monthlyUploadLimit: 2500,
- value: 'users-teamy',
+ value: Plans.USERS_TEAMY,
}
const trialPlan = {
marketingName: 'Pro Trial Team',
- value: 'users-trial',
+ value: Plans.USERS_TRIAL,
billingRate: null,
baseUnitPrice: 12,
benefits: ['Configurable # of users', 'Unlimited repos'],
@@ -198,7 +198,7 @@ const mockPlanDataResponseMonthly = {
billingRate: 'monthly',
marketingName: 'Pro Team',
monthlyUploadLimit: 250,
- value: 'test-plan',
+ value: Plans.USERS_PR_INAPPM,
trialStatus: TrialStatuses.NOT_STARTED,
trialStartDate: '',
trialEndDate: '',
@@ -214,7 +214,7 @@ const mockPlanDataResponseYearly = {
billingRate: 'yearly',
marketingName: 'Pro Team',
monthlyUploadLimit: 250,
- value: 'test-plan',
+ value: Plans.USERS_PR_INAPPY,
trialStatus: TrialStatuses.NOT_STARTED,
trialStartDate: '',
trialEndDate: '',
@@ -231,11 +231,6 @@ const queryClient = new QueryClient({
retry: false,
},
},
- logger: {
- error: () => {},
- warn: () => {},
- log: () => {},
- },
})
const server = setupServer()
@@ -320,7 +315,7 @@ describe('UpgradeForm', () => {
}
}),
http.patch(
- '/internal/:provider/:owner/account-details/',
+ `/internal/:provider/:owner/account-details/`,
async (info) => {
if (!successfulPatchRequest) {
if (errorDetails) {
@@ -379,7 +374,7 @@ describe('UpgradeForm', () => {
setSelectedPlan: vi.fn(),
selectedPlan: {
value: Plans.USERS_PR_INAPPY,
- } as NonNullable,
+ } as NonNullable,
}
it('renders the organization and owner titles', async () => {
setup({ planValue: Plans.USERS_BASIC })
@@ -687,7 +682,7 @@ describe('UpgradeForm', () => {
setSelectedPlan: vi.fn(),
selectedPlan: {
value: Plans.USERS_PR_INAPPY,
- } as NonNullable,
+ } as NonNullable,
}
it('renders the organization and owner titles', async () => {
setup({ planValue: Plans.USERS_PR_INAPPM })
@@ -990,7 +985,7 @@ describe('UpgradeForm', () => {
setSelectedPlan: vi.fn(),
selectedPlan: {
value: Plans.USERS_PR_INAPPY,
- } as NonNullable,
+ } as NonNullable,
}
it('renders the organization and owner titles', async () => {
setup({ planValue: Plans.USERS_PR_INAPPY })
@@ -1317,7 +1312,7 @@ describe('UpgradeForm', () => {
setSelectedPlan: vi.fn(),
selectedPlan: {
value: Plans.USERS_SENTRYY,
- } as NonNullable,
+ } as NonNullable,
}
it('renders the organization and owner titles', async () => {
setup({
@@ -1637,7 +1632,7 @@ describe('UpgradeForm', () => {
setSelectedPlan: vi.fn(),
selectedPlan: {
value: Plans.USERS_TEAMY,
- } as NonNullable,
+ } as NonNullable,
}
it('renders the organization and owner titles', async () => {
setup({
@@ -1984,7 +1979,7 @@ describe('UpgradeForm', () => {
setSelectedPlan: vi.fn(),
selectedPlan: {
value: Plans.USERS_PR_INAPPY,
- } as NonNullable,
+ } as NonNullable,
}
describe('user chooses less than the number of active users', () => {
it('does not display an error', async () => {
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpgradeForm.tsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpgradeForm.tsx
index 349cabf212..85b1ed5384 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpgradeForm.tsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradeForm/UpgradeForm.tsx
@@ -4,7 +4,6 @@ import { useForm } from 'react-hook-form'
import { useParams } from 'react-router-dom'
import {
- IndividualPlan,
useAccountDetails,
useAvailablePlans,
usePlanData,
@@ -13,6 +12,8 @@ import {
canApplySentryUpgrade,
getNextBillingDate,
isTeamPlan,
+ Plan,
+ PlanName,
} from 'shared/utils/billing'
import {
getDefaultValuesUpgradeForm,
@@ -21,7 +22,6 @@ import {
MIN_SENTRY_SEATS,
} from 'shared/utils/upgradeForm'
-import { NewPlanType } from './constants'
import Controller from './Controllers/Controller'
import { useUpgradeControls } from './hooks'
import PlanTypeOptions from './PlanTypeOptions'
@@ -34,12 +34,12 @@ type URLParams = {
}
type UpgradeFormProps = {
- selectedPlan: NonNullable
- setSelectedPlan: (plan: IndividualPlan) => void
+ selectedPlan: NonNullable
+ setSelectedPlan: (plan?: Plan) => void
}
export type UpgradeFormFields = {
- newPlan: NewPlanType
+ newPlan?: PlanName
seats: number
}
@@ -67,7 +67,7 @@ function UpgradeForm({ selectedPlan, setSelectedPlan }: UpgradeFormProps) {
formState: { isValid, errors },
setValue: setFormValue,
trigger,
- } = useForm({
+ } = useForm({
defaultValues: getDefaultValuesUpgradeForm({
accountDetails,
plans,
@@ -108,7 +108,7 @@ function UpgradeForm({ selectedPlan, setSelectedPlan }: UpgradeFormProps) {
newPlan={newPlan}
/>
{
+ const { provider, owner } = useParams()
+ const queryClient = useQueryClient()
+ const history = useHistory()
+ const addToast = useAddNotification()
+ const { mutate } = useUpgradePlan({ provider, owner })
+ const setPlanUpdatedNotification = useSetPlanUpdatedNotification()
+
+ function upgradePlan({ seats, newPlan }: UpgradeFormFields) {
+ return mutate(
+ {
+ seats,
+ newPlan: newPlan!,
+ },
+ {
+ onSuccess: () => {
+ queryClient.invalidateQueries(['accountDetails'])
+ setPlanUpdatedNotification({
+ alertOption: 'success',
+ })
+ history.push(`/plan/${provider}/${owner}`)
+ },
+ onError: (error: any) => {
+ addToast({
+ type: 'error',
+ text: error?.data?.detail || 'Something went wrong',
+ })
+ },
+ }
+ )
+ }
+
+ return {
+ upgradePlan,
+ }
+}
diff --git a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradePlanPage.test.jsx b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradePlanPage.test.jsx
index 74def6bd24..b6dcebf94d 100644
--- a/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradePlanPage.test.jsx
+++ b/src/pages/PlanPage/subRoutes/UpgradePlanPage/UpgradePlanPage.test.jsx
@@ -20,7 +20,7 @@ vi.mock('./UpgradeForm', () => ({ default: () => 'UpgradeForm' }))
const plans = [
{
marketingName: 'Basic',
- value: 'users-free',
+ value: Plans.USERS_FREE,
billingRate: null,
baseUnitPrice: 0,
benefits: [
@@ -32,7 +32,7 @@ const plans = [
},
{
marketingName: 'Pro Team',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -45,7 +45,7 @@ const plans = [
},
{
marketingName: 'Pro Team',
- value: 'users-pr-inappy',
+ value: Plans.USERS_PR_INAPPY,
billingRate: 'annually',
baseUnitPrice: 10,
benefits: [
@@ -58,7 +58,7 @@ const plans = [
},
{
marketingName: 'Pro Team',
- value: 'users-enterprisem',
+ value: Plans.USERS_ENTERPRISEM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -71,7 +71,7 @@ const plans = [
},
{
marketingName: 'Pro Team',
- value: 'users-enterprisey',
+ value: Plans.USERS_ENTERPRISEY,
billingRate: 'annually',
baseUnitPrice: 10,
benefits: [
@@ -86,7 +86,7 @@ const plans = [
const sentryPlanMonth = {
marketingName: 'Sentry Pro Team',
- value: 'users-sentrym',
+ value: Plans.USERS_SENTRYM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -101,7 +101,7 @@ const sentryPlanMonth = {
const sentryPlanYear = {
marketingName: 'Sentry Pro Team',
- value: 'users-sentryy',
+ value: Plans.USERS_SENTRYY,
billingRate: 'annually',
baseUnitPrice: 10,
benefits: [
@@ -120,7 +120,7 @@ const teamPlanMonth = {
billingRate: 'monthly',
marketingName: 'Users Team',
monthlyUploadLimit: 2500,
- value: 'users-teamm',
+ value: Plans.USERS_TEAMM,
}
const teamPlanYear = {
@@ -129,7 +129,7 @@ const teamPlanYear = {
billingRate: 'annually',
marketingName: 'Users Team',
monthlyUploadLimit: 2500,
- value: 'users-teamy',
+ value: Plans.USERS_TEAMY,
}
const mockPlanData = {
@@ -138,7 +138,7 @@ const mockPlanData = {
billingRate: 'monthly',
marketingName: 'Users Basic',
monthlyUploadLimit: 250,
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
trialStatus: TrialStatuses.NOT_STARTED,
trialStartDate: '',
trialEndDate: '',
diff --git a/src/pages/PullRequestPage/Header/HeaderDefault/HeaderDefault.tsx b/src/pages/PullRequestPage/Header/HeaderDefault/HeaderDefault.tsx
index eddb52502c..2c6096da60 100644
--- a/src/pages/PullRequestPage/Header/HeaderDefault/HeaderDefault.tsx
+++ b/src/pages/PullRequestPage/Header/HeaderDefault/HeaderDefault.tsx
@@ -2,6 +2,7 @@ import cs from 'classnames'
import capitalize from 'lodash/capitalize'
import { useParams } from 'react-router-dom'
+import { Provider } from 'shared/api/helpers'
import { formatTimeToNow } from 'shared/utils/dates'
import { getProviderPullURL } from 'shared/utils/provider'
import A from 'ui/A'
@@ -13,7 +14,7 @@ import { usePullHeadData } from './hooks'
import { pullStateToColor } from '../constants'
interface URLParams {
- provider: string
+ provider: Provider
owner: string
repo: string
pullId: string
diff --git a/src/pages/PullRequestPage/Header/HeaderTeam/HeaderTeam.tsx b/src/pages/PullRequestPage/Header/HeaderTeam/HeaderTeam.tsx
index fc2b0e337f..2e32879725 100644
--- a/src/pages/PullRequestPage/Header/HeaderTeam/HeaderTeam.tsx
+++ b/src/pages/PullRequestPage/Header/HeaderTeam/HeaderTeam.tsx
@@ -2,6 +2,7 @@ import cs from 'classnames'
import capitalize from 'lodash/capitalize'
import { useParams } from 'react-router-dom'
+import { Provider } from 'shared/api/helpers'
import { formatTimeToNow } from 'shared/utils/dates'
import { getProviderPullURL } from 'shared/utils/provider'
import A from 'ui/A'
@@ -14,7 +15,7 @@ import { usePullHeadDataTeam } from './hooks'
import { pullStateToColor } from '../constants'
interface URLParams {
- provider: string
+ provider: Provider
owner: string
repo: string
pullId: string
diff --git a/src/pages/RepoPage/ActivationAlert/ActivationAlert.test.tsx b/src/pages/RepoPage/ActivationAlert/ActivationAlert.test.tsx
index 66aa517888..1305713210 100644
--- a/src/pages/RepoPage/ActivationAlert/ActivationAlert.test.tsx
+++ b/src/pages/RepoPage/ActivationAlert/ActivationAlert.test.tsx
@@ -4,6 +4,8 @@ import { graphql, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { MemoryRouter, Route } from 'react-router-dom'
+import { PlanName, Plans } from 'shared/utils/billing'
+
import ActivationAlert from './ActivationAlert'
vi.mock('./FreePlanSeatsTakenAlert', () => ({
@@ -48,7 +50,7 @@ const mockTrialData = {
billingRate: 'monthly',
marketingName: 'Users Basic',
monthlyUploadLimit: 250,
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
trialStatus: 'ONGOING',
trialStartDate: '2023-01-01T08:55:25',
trialEndDate: '2023-01-10T08:55:25',
@@ -61,7 +63,7 @@ const mockTrialData = {
describe('ActivationAlert', () => {
function setup(
privateRepos = true,
- value = 'users-basic',
+ value: PlanName = Plans.USERS_BASIC,
hasSeatsLeft = true
) {
server.use(
@@ -81,7 +83,7 @@ describe('ActivationAlert', () => {
billingRate: 'monthly',
marketingName: 'Users Basic',
monthlyUploadLimit: 250,
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
},
},
},
@@ -101,7 +103,7 @@ describe('ActivationAlert', () => {
})
it('renders FreePlanSeatsTakenAlert when on free plan and no seats left', async () => {
- setup(false, 'users-basic', false)
+ setup(false, Plans.USERS_BASIC, false)
render(, { wrapper })
const freePlanSeatsTakenAlert = await screen.findByText(
@@ -111,7 +113,7 @@ describe('ActivationAlert', () => {
})
it('renders PaidPlanSeatsTakenAlert when on paid plan and no seats left', async () => {
- setup(false, 'users-pro', false)
+ setup(false, Plans.USERS_PR_INAPPM, false)
render(, { wrapper })
const paidPlanSeatsTakenAlert = await screen.findByText(
@@ -121,7 +123,7 @@ describe('ActivationAlert', () => {
})
it('renders ActivationRequiredAlert when on paid plan and some seats left', async () => {
- setup(false, 'users-pro', true)
+ setup(false, Plans.USERS_PR_INAPPM, true)
render(, { wrapper })
const activationRequiredAlert = await screen.findByText(
diff --git a/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationBanner.test.tsx b/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationBanner.test.tsx
index 604b89e28d..0fecd53bcf 100644
--- a/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationBanner.test.tsx
+++ b/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationBanner.test.tsx
@@ -4,6 +4,8 @@ import { graphql, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { MemoryRouter, Route } from 'react-router-dom'
+import { PlanName, Plans } from 'shared/utils/billing'
+
import ActivationBanner from './ActivationBanner'
vi.mock('./TrialEligibleBanner', () => ({
@@ -48,7 +50,7 @@ const mockTrialData = {
billingRate: 'monthly',
marketingName: 'Users Basic',
monthlyUploadLimit: 250,
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
trialStatus: 'ONGOING',
trialStartDate: '2023-01-01T08:55:25',
trialEndDate: '2023-01-10T08:55:25',
@@ -62,7 +64,7 @@ describe('ActivationBanner', () => {
function setup(
privateRepos = true,
trialStatus = 'NOT_STARTED',
- value = 'users-basic',
+ value: PlanName = Plans.USERS_BASIC,
hasSeatsLeft = true
) {
server.use(
@@ -83,7 +85,7 @@ describe('ActivationBanner', () => {
billingRate: 'monthly',
marketingName: 'Users Basic',
monthlyUploadLimit: 250,
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
},
},
},
@@ -101,7 +103,7 @@ describe('ActivationBanner', () => {
})
it('does not render trial eligible banner if user is not eligible to trial', async () => {
- setup(false, 'ONGOING', 'users-basic', true)
+ setup(false, 'ONGOING', Plans.USERS_BASIC, true)
const { container } = render(, { wrapper })
await waitFor(() => queryClient.isFetching)
@@ -111,7 +113,7 @@ describe('ActivationBanner', () => {
})
it('renders activation required banner if user is not on free plan and has seats left', async () => {
- setup(true, 'ONGOING', 'users-pro', true)
+ setup(true, 'ONGOING', Plans.USERS_PR_INAPPM, true)
render(, { wrapper })
const ActivationRequiredBanner = await screen.findByText(
@@ -121,7 +123,7 @@ describe('ActivationBanner', () => {
})
it('renders seats limit reached banner if user has no seats left and on free plan', async () => {
- setup(true, 'ONGOING', 'users-basic', false)
+ setup(true, 'ONGOING', Plans.USERS_BASIC, false)
render(, { wrapper })
const FreePlanSeatsLimitBanner = await screen.findByText(
@@ -131,7 +133,7 @@ describe('ActivationBanner', () => {
})
it('renders seats limit reached banner if user has no seats left and on paid plan', async () => {
- setup(true, 'ONGOING', 'users-inappy', false)
+ setup(true, 'ONGOING', Plans.USERS_PR_INAPPY, false)
render(, { wrapper })
const PaidPlanSeatsLimitBanner = await screen.findByText(
diff --git a/src/pages/RepoPage/CoverageOnboarding/CircleCI/CircleCI.tsx b/src/pages/RepoPage/CoverageOnboarding/CircleCI/CircleCI.tsx
index 6ee1cd2869..a957619aaf 100644
--- a/src/pages/RepoPage/CoverageOnboarding/CircleCI/CircleCI.tsx
+++ b/src/pages/RepoPage/CoverageOnboarding/CircleCI/CircleCI.tsx
@@ -6,6 +6,7 @@ import {
} from 'services/codecovEventMetrics'
import { useOrgUploadToken } from 'services/orgUploadToken'
import { useRepo } from 'services/repo'
+import { Provider } from 'shared/api/helpers'
import { useFlags } from 'shared/featureFlags'
import { providerToInternalProvider } from 'shared/utils/provider'
import A from 'ui/A'
@@ -25,7 +26,7 @@ workflows:
`
interface URLParams {
- provider: string
+ provider: Provider
owner: string
repo: string
}
@@ -51,7 +52,7 @@ function CircleCI() {
diff --git a/src/pages/RepoPage/CoverageOnboarding/NewRepoTab.tsx b/src/pages/RepoPage/CoverageOnboarding/NewRepoTab.tsx
index 50bdd67712..5d20079772 100644
--- a/src/pages/RepoPage/CoverageOnboarding/NewRepoTab.tsx
+++ b/src/pages/RepoPage/CoverageOnboarding/NewRepoTab.tsx
@@ -10,6 +10,7 @@ import {
} from 'services/codecovEventMetrics'
import { useNavLinks } from 'services/navigation'
import { useRepo } from 'services/repo'
+import { Provider } from 'shared/api/helpers'
import { useRedirect } from 'shared/useRedirect'
import { providerToName } from 'shared/utils'
import A from 'ui/A'
@@ -37,7 +38,7 @@ const CI_PROVIDERS = {
type CIProviderValue = (typeof CI_PROVIDERS)[keyof typeof CI_PROVIDERS]
type CIUrls = Record
-const getInitialProvider = (provider: string, path: string, urls: CIUrls) => {
+const getInitialProvider = (provider: Provider, path: string, urls: CIUrls) => {
const defaultProvider =
providerToName(provider) !== 'Github'
? CI_PROVIDERS.OtherCI
@@ -52,7 +53,7 @@ const getInitialProvider = (provider: string, path: string, urls: CIUrls) => {
}
interface CISelectorProps {
- provider: string
+ provider: Provider
owner: string
repo: string
}
@@ -124,7 +125,7 @@ function Content() {
}
interface URLParams {
- provider: string
+ provider: Provider
owner: string
repo: string
}
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/FailedTestsTable/FailedTestsTable.test.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/FailedTestsTable/FailedTestsTable.test.tsx
index 7941639294..18e431128c 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/FailedTestsTable/FailedTestsTable.test.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/FailedTestsTable/FailedTestsTable.test.tsx
@@ -11,6 +11,8 @@ import { setupServer } from 'msw/node'
import { mockIsIntersecting } from 'react-intersection-observer/test-utils'
import { MemoryRouter, Route } from 'react-router-dom'
+import { Plans } from 'shared/utils/billing'
+
import FailedTestsTable from './FailedTestsTable'
import {
@@ -132,7 +134,7 @@ interface SetupArgs {
describe('FailedTestsTable', () => {
function setup({
noEntries = false,
- planValue = 'users-enterprisem',
+ planValue = Plans.USERS_ENTERPRISEM,
isPrivate = false,
}: SetupArgs) {
const queryClient = new QueryClient({
@@ -215,7 +217,7 @@ describe('FailedTestsTable', () => {
describe('when plan is team plan', () => {
it('does not render flake rate column', async () => {
const { queryClient } = setup({
- planValue: 'users-teamm',
+ planValue: Plans.USERS_TEAMM,
isPrivate: true,
})
render(, {
@@ -232,7 +234,7 @@ describe('FailedTestsTable', () => {
describe('when plan is free', () => {
it('does not render flake rate column', async () => {
const { queryClient } = setup({
- planValue: 'users-free',
+ planValue: Plans.USERS_FREE,
isPrivate: true,
})
render(, {
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.test.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.test.tsx
index 4b9cfbae7a..b67cd0b310 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.test.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.test.tsx
@@ -6,12 +6,14 @@ import { setupServer } from 'msw/node'
import { PropsWithChildren, Suspense } from 'react'
import { MemoryRouter, Route, useLocation } from 'react-router-dom'
+import { PlanName, Plans } from 'shared/utils/billing'
+
import MetricsSection, { historicalTrendToCopy } from './MetricsSection'
import { TestResultsFilterParameter } from '../hooks/useInfiniteTestResults/useInfiniteTestResults'
const mockAggResponse = (
- planValue = 'users-enterprisem',
+ planValue: PlanName = Plans.USERS_ENTERPRISEM,
isPrivate = false
) => ({
owner: {
@@ -101,7 +103,10 @@ afterAll(() => {
})
describe('MetricsSection', () => {
- function setup(planValue = 'users-enterprisem', isPrivate = false) {
+ function setup(
+ planValue: PlanName = Plans.USERS_ENTERPRISEM,
+ isPrivate = false
+ ) {
const user = userEvent.setup()
server.use(
@@ -419,7 +424,7 @@ describe('MetricsSection', () => {
describe('when on team plan', () => {
describe('when repo is private', () => {
it('does not render total flaky tests card', async () => {
- setup('users-teamm', true)
+ setup(Plans.USERS_TEAMM, true)
render(, {
wrapper: wrapper('/gh/owner/repo/tests/main'),
})
@@ -431,7 +436,7 @@ describe('MetricsSection', () => {
})
it('does not render avg flaky tests card', async () => {
- setup('users-teamm', true)
+ setup(Plans.USERS_TEAMM, true)
render(, {
wrapper: wrapper('/gh/owner/repo/tests/main'),
})
@@ -445,7 +450,7 @@ describe('MetricsSection', () => {
describe('when repo is public', () => {
it('renders total flaky tests card', async () => {
- setup('users-teamm', false)
+ setup(Plans.USERS_TEAMM, false)
render(, {
wrapper: wrapper('/gh/owner/repo/tests/main'),
})
@@ -457,7 +462,7 @@ describe('MetricsSection', () => {
})
it('renders avg flaky tests card', async () => {
- setup('users-teamm', false)
+ setup(Plans.USERS_TEAMM, false)
render(, {
wrapper: wrapper('/gh/owner/repo/tests/main'),
})
@@ -473,7 +478,7 @@ describe('MetricsSection', () => {
describe('when on free plan', () => {
describe('when repo is private', () => {
it('does not render total flaky tests card', async () => {
- setup('users-basic', true)
+ setup(Plans.USERS_BASIC, true)
render(, {
wrapper: wrapper('/gh/owner/repo/tests/main'),
})
@@ -485,7 +490,7 @@ describe('MetricsSection', () => {
})
it('does not render avg flaky tests card', async () => {
- setup('users-basic', true)
+ setup(Plans.USERS_BASIC, true)
render(, {
wrapper: wrapper('/gh/owner/repo/tests/main'),
})
@@ -499,7 +504,7 @@ describe('MetricsSection', () => {
describe('when repo is public', () => {
it('renders total flaky tests card', async () => {
- setup('users-basic', false)
+ setup(Plans.USERS_BASIC, false)
render(, {
wrapper: wrapper('/gh/owner/repo/tests/main'),
})
@@ -511,7 +516,7 @@ describe('MetricsSection', () => {
})
it('renders avg flaky tests card', async () => {
- setup('users-basic', false)
+ setup(Plans.USERS_BASIC, false)
render(, {
wrapper: wrapper('/gh/owner/repo/tests/main'),
})
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useInfiniteTestResults/useInfiniteTestResults.test.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useInfiniteTestResults/useInfiniteTestResults.test.tsx
index 6d8019c623..f8db7f50c1 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useInfiniteTestResults/useInfiniteTestResults.test.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useInfiniteTestResults/useInfiniteTestResults.test.tsx
@@ -3,12 +3,14 @@ import { renderHook, waitFor } from '@testing-library/react'
import { graphql, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
+import { Plans } from 'shared/utils/billing'
+
import { useInfiniteTestResults } from './useInfiniteTestResults'
const mockTestResults = {
owner: {
plan: {
- value: 'users-enterprisem',
+ value: Plans.USERS_ENTERPRISEM,
},
repository: {
__typename: 'Repository',
@@ -78,7 +80,7 @@ const mockNotFoundError = {
message: 'Repository not found',
},
plan: {
- value: 'users-enterprisem',
+ value: Plans.USERS_ENTERPRISEM,
},
},
}
@@ -86,7 +88,7 @@ const mockNotFoundError = {
const mockOwnerNotActivatedError = {
owner: {
plan: {
- value: 'users-enterprisem',
+ value: Plans.USERS_ENTERPRISEM,
},
repository: {
__typename: 'OwnerNotActivatedError',
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useInfiniteTestResults/useInfiniteTestResults.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useInfiniteTestResults/useInfiniteTestResults.tsx
index 9cedc862bc..101ae8050b 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useInfiniteTestResults/useInfiniteTestResults.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useInfiniteTestResults/useInfiniteTestResults.tsx
@@ -12,6 +12,7 @@ import {
} from 'services/repo'
import Api from 'shared/api'
import { type NetworkErrorObject, rejectNetworkError } from 'shared/api/helpers'
+import { PlanName, Plans } from 'shared/utils/billing'
import { mapEdges } from 'shared/utils/graphql'
import A from 'ui/A'
@@ -63,7 +64,7 @@ const GetTestResultsSchema = z.object({
.object({
plan: z
.object({
- value: z.string(),
+ value: z.nativeEnum(Plans),
})
.nullable(),
repository: z.discriminatedUnion('__typename', [
@@ -178,7 +179,7 @@ interface UseTestResultsArgs {
testResults: TestResult[]
pageInfo: { endCursor: string | null; hasNextPage: boolean }
private: boolean | null
- plan: string | null
+ plan: PlanName | null
defaultBranch: string | null
totalCount: number | null
}>
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useTestResultsAggregates/useTestResultsAggregates.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useTestResultsAggregates/useTestResultsAggregates.tsx
index 4473187420..851fac6f14 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useTestResultsAggregates/useTestResultsAggregates.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useTestResultsAggregates/useTestResultsAggregates.tsx
@@ -6,13 +6,14 @@ import { MeasurementInterval } from 'pages/RepoPage/shared/constants'
import { RepoNotFoundErrorSchema } from 'services/repo'
import Api from 'shared/api'
import { NetworkErrorObject, rejectNetworkError } from 'shared/api/helpers'
+import { Plans } from 'shared/utils/billing'
const TestResultsAggregatesSchema = z.object({
owner: z
.object({
plan: z
.object({
- value: z.string(),
+ value: z.nativeEnum(Plans),
})
.nullable(),
repository: z.discriminatedUnion('__typename', [
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useTestResultsAggregates/useTestsResultsAggregates.test.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useTestResultsAggregates/useTestsResultsAggregates.test.tsx
index 1505050332..94d8666917 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useTestResultsAggregates/useTestsResultsAggregates.test.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/hooks/useTestResultsAggregates/useTestsResultsAggregates.test.tsx
@@ -5,6 +5,8 @@ import { setupServer } from 'msw/node'
import { MemoryRouter, Route } from 'react-router-dom'
import { MockInstance } from 'vitest'
+import { Plans } from 'shared/utils/billing'
+
import { useTestResultsAggregates } from './useTestResultsAggregates'
const queryClient = new QueryClient({
@@ -41,7 +43,7 @@ const mockNotFoundError = {
message: 'repo not found',
},
plan: {
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
},
},
}
@@ -52,7 +54,7 @@ const mockIncorrectResponse = {
invalid: 'invalid',
},
plan: {
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
},
},
}
@@ -60,7 +62,7 @@ const mockIncorrectResponse = {
const mockResponse = {
owner: {
plan: {
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
},
repository: {
__typename: 'Repository',
diff --git a/src/pages/SyncProviderPage/SyncButton.tsx b/src/pages/SyncProviderPage/SyncButton.tsx
index 4e81d28f01..5044a1a8e5 100644
--- a/src/pages/SyncProviderPage/SyncButton.tsx
+++ b/src/pages/SyncProviderPage/SyncButton.tsx
@@ -1,8 +1,10 @@
import { useNavLinks } from 'services/navigation'
-import { providerImage, providerToName } from 'shared/utils/provider'
+import { Provider } from 'shared/api/helpers'
+import { loginProviderImage } from 'shared/utils/loginProviders'
+import { providerToName } from 'shared/utils/provider'
interface SyncButtonProps {
- provider: 'gh' | 'gl' | 'bb' | 'ghe' | 'gle' | 'bbs'
+ provider: Provider
}
const SyncButton: React.FC = ({ provider }) => {
@@ -19,7 +21,7 @@ const SyncButton: React.FC = ({ provider }) => {
Sync with {providerToName(provider)}
diff --git a/src/services/account/mocks.ts b/src/services/account/mocks.ts
index b35bdd60e4..dffcb14748 100644
--- a/src/services/account/mocks.ts
+++ b/src/services/account/mocks.ts
@@ -1,3 +1,5 @@
+import { Plans } from 'shared/utils/billing'
+
/* eslint-disable camelcase */
export const invoiceObject = {
amountDue: 1407.0,
@@ -39,7 +41,7 @@ export const accountDetailsObject = {
plan_auto_activate: true,
plan: {
marketing_name: 'Pro Team',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billing_rate: 'monthly',
base_unit_price: 12,
benefits: [
@@ -78,7 +80,7 @@ export const accountDetailsObject = {
end: 1636479475,
start: 1634910008,
},
- plan_name: 'users-pr-inappm',
+ plan_name: Plans.USERS_PR_INAPPM,
quantity: 21,
},
{
@@ -90,7 +92,7 @@ export const accountDetailsObject = {
end: 1636479475,
start: 1634910008,
},
- plan_name: 'users-pr-inappm',
+ plan_name: Plans.USERS_PR_INAPPM,
quantity: 23,
},
],
@@ -153,7 +155,7 @@ export const accountDetailsParsedObj = {
planAutoActivate: true,
plan: {
marketingName: 'Pro Team',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -192,7 +194,7 @@ export const accountDetailsParsedObj = {
end: 1636479475,
start: 1634910008,
},
- planName: 'users-pr-inappm',
+ planName: Plans.USERS_PR_INAPPM,
quantity: 21,
},
{
@@ -204,7 +206,7 @@ export const accountDetailsParsedObj = {
end: 1636479475,
start: 1634910008,
},
- planName: 'users-pr-inappm',
+ planName: Plans.USERS_PR_INAPPM,
quantity: 23,
},
],
diff --git a/src/services/account/useAccountDetails.ts b/src/services/account/useAccountDetails.ts
index 2df7f01843..3395d707e1 100644
--- a/src/services/account/useAccountDetails.ts
+++ b/src/services/account/useAccountDetails.ts
@@ -3,6 +3,7 @@ import { z } from 'zod'
import Api from 'shared/api'
import { NetworkErrorObject } from 'shared/api/helpers'
+import { Plans } from 'shared/utils/billing'
const InvoiceSchema = z
.object({
@@ -120,7 +121,7 @@ export const PlanSchema = z
marketingName: z.string(),
monthlyUploadLimit: z.number().nullish(),
quantity: z.number().nullish(),
- value: z.string(),
+ value: z.nativeEnum(Plans),
trialDays: z.number().nullish(),
})
.nullable()
diff --git a/src/services/account/useAvailablePlans.test.tsx b/src/services/account/useAvailablePlans.test.tsx
index 427f86cee3..4924fa8653 100644
--- a/src/services/account/useAvailablePlans.test.tsx
+++ b/src/services/account/useAvailablePlans.test.tsx
@@ -3,12 +3,14 @@ import { renderHook, waitFor } from '@testing-library/react'
import { graphql, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
+import { Plans } from 'shared/utils/billing'
+
import { useAvailablePlans } from './useAvailablePlans'
const mockAvailablePlans = [
{
marketingName: 'Basic',
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
billingRate: null,
baseUnitPrice: 0,
benefits: [
@@ -20,7 +22,7 @@ const mockAvailablePlans = [
},
{
marketingName: 'Pro Team',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -33,7 +35,7 @@ const mockAvailablePlans = [
},
{
marketingName: 'Pro Team',
- value: 'users-pr-inappy',
+ value: Plans.USERS_PR_INAPPY,
billingRate: 'annually',
baseUnitPrice: 10,
benefits: [
@@ -46,7 +48,7 @@ const mockAvailablePlans = [
},
{
marketingName: 'Sentry Pro Team',
- value: 'users-sentryy',
+ value: Plans.USERS_SENTRYY,
billingRate: 'annually',
baseUnitPrice: 10,
benefits: [
@@ -59,7 +61,7 @@ const mockAvailablePlans = [
},
{
marketingName: 'Pro Team',
- value: 'users-enterprisem',
+ value: Plans.USERS_ENTERPRISEM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -72,7 +74,7 @@ const mockAvailablePlans = [
},
{
marketingName: 'Pro Team',
- value: 'users-enterprisey',
+ value: Plans.USERS_ENTERPRISEY,
billingRate: 'annually',
baseUnitPrice: 10,
benefits: [
@@ -85,7 +87,7 @@ const mockAvailablePlans = [
},
{
marketingName: 'Team',
- value: 'users-teamm',
+ value: Plans.USERS_TEAMM,
billingRate: 'monthly',
baseUnitPrice: 6,
benefits: ['Patch coverage analysis'],
diff --git a/src/services/account/useAvailablePlans.ts b/src/services/account/useAvailablePlans.ts
index 8d92947912..14e0ba3939 100644
--- a/src/services/account/useAvailablePlans.ts
+++ b/src/services/account/useAvailablePlans.ts
@@ -2,19 +2,16 @@ import { useQuery } from '@tanstack/react-query'
import { z } from 'zod'
import Api from 'shared/api'
+import { Plans } from 'shared/utils/billing'
-const IndividualPlanSchema = z
- .object({
- baseUnitPrice: z.number(),
- benefits: z.array(z.string()),
- billingRate: z.string().nullable(),
- marketingName: z.string(),
- monthlyUploadLimit: z.number().nullable(),
- value: z.string(),
- })
- .nullable()
-
-export type IndividualPlan = z.infer
+const IndividualPlanSchema = z.object({
+ baseUnitPrice: z.number(),
+ benefits: z.array(z.string()),
+ billingRate: z.string().nullable(),
+ marketingName: z.string(),
+ monthlyUploadLimit: z.number().nullable(),
+ value: z.nativeEnum(Plans),
+})
const PlansSchema = z
.object({
diff --git a/src/services/account/useCancelPlan.test.jsx b/src/services/account/useCancelPlan.test.jsx
index e2435751de..a780061f27 100644
--- a/src/services/account/useCancelPlan.test.jsx
+++ b/src/services/account/useCancelPlan.test.jsx
@@ -30,7 +30,7 @@ const accountDetails = {
baseUnitPrice: 12,
benefits: ['Configurable # of users', 'Unlimited repos'],
quantity: 5,
- value: 'users-inappm',
+ value: Plans.USERS_INAPPM,
},
activatedUserCount: 2,
inactiveUserCount: 1,
diff --git a/src/services/account/usePlanData.test.tsx b/src/services/account/usePlanData.test.tsx
index ff31b08427..333090e425 100644
--- a/src/services/account/usePlanData.test.tsx
+++ b/src/services/account/usePlanData.test.tsx
@@ -3,6 +3,8 @@ import { renderHook, waitFor } from '@testing-library/react'
import { graphql, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
+import { Plans } from 'shared/utils/billing'
+
import { usePlanData } from './usePlanData'
const mockTrialData = {
@@ -13,7 +15,7 @@ const mockTrialData = {
billingRate: 'monthly',
marketingName: 'Users Basic',
monthlyUploadLimit: 250,
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
trialStatus: 'ONGOING',
trialStartDate: '2023-01-01T08:55:25',
trialEndDate: '2023-01-10T08:55:25',
@@ -28,7 +30,7 @@ const mockTrialData = {
billingRate: 'monthly',
marketingName: 'Users Basic',
monthlyUploadLimit: 250,
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
},
}
@@ -86,7 +88,7 @@ describe('usePlanData', () => {
billingRate: 'monthly',
marketingName: 'Users Basic',
monthlyUploadLimit: 250,
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
trialStatus: 'ONGOING',
trialStartDate: '2023-01-01T08:55:25',
trialEndDate: '2023-01-10T08:55:25',
@@ -101,7 +103,7 @@ describe('usePlanData', () => {
billingRate: 'monthly',
marketingName: 'Users Basic',
monthlyUploadLimit: 250,
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
},
})
)
diff --git a/src/services/account/usePlanData.ts b/src/services/account/usePlanData.ts
index 0852670af7..1648769d71 100644
--- a/src/services/account/usePlanData.ts
+++ b/src/services/account/usePlanData.ts
@@ -2,6 +2,7 @@ import { useQuery } from '@tanstack/react-query'
import { z } from 'zod'
import Api from 'shared/api'
+import { Plans } from 'shared/utils/billing'
export const TrialStatuses = {
NOT_STARTED: 'NOT_STARTED',
@@ -16,7 +17,7 @@ const PlanSchema = z.object({
billingRate: z.string().nullable(),
marketingName: z.string(),
monthlyUploadLimit: z.number().nullable(),
- value: z.string(),
+ value: z.nativeEnum(Plans),
pretrialUsersCount: z.number().nullable(),
trialEndDate: z.string().nullable(),
trialStatus: z.nativeEnum(TrialStatuses),
diff --git a/src/services/account/useUpdateBillingAddress.test.tsx b/src/services/account/useUpdateBillingAddress.test.tsx
index b8a266b117..4b2e32722e 100644
--- a/src/services/account/useUpdateBillingAddress.test.tsx
+++ b/src/services/account/useUpdateBillingAddress.test.tsx
@@ -3,6 +3,8 @@ import { renderHook, waitFor } from '@testing-library/react'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
+import { Plans } from 'shared/utils/billing'
+
import { useUpdateBillingAddress } from './useUpdateBillingAddress'
const queryClient = new QueryClient({
@@ -36,7 +38,7 @@ const accountDetails = {
baseUnitPrice: 12,
benefits: ['Configurable # of users', 'Unlimited repos'],
quantity: 5,
- value: 'users-inappm',
+ value: Plans.USERS_PR_INAPPM,
},
subscription_detail: {
latest_invoice: {
diff --git a/src/services/account/useUpdateBillingEmail.test.tsx b/src/services/account/useUpdateBillingEmail.test.tsx
index dac81cb586..4151927605 100644
--- a/src/services/account/useUpdateBillingEmail.test.tsx
+++ b/src/services/account/useUpdateBillingEmail.test.tsx
@@ -3,6 +3,8 @@ import { renderHook, waitFor } from '@testing-library/react'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
+import { Plans } from 'shared/utils/billing'
+
import { useUpdateBillingEmail } from './useUpdateBillingEmail'
const queryClient = new QueryClient({
@@ -36,7 +38,7 @@ const accountDetails = {
baseUnitPrice: 12,
benefits: ['Configurable # of users', 'Unlimited repos'],
quantity: 5,
- value: 'users-inappm',
+ value: Plans.USERS_PR_INAPPM,
},
subscription_detail: {
latest_invoice: {
diff --git a/src/services/account/useUpdateCard.test.tsx b/src/services/account/useUpdateCard.test.tsx
index c5c5ede609..fdcc31c7ac 100644
--- a/src/services/account/useUpdateCard.test.tsx
+++ b/src/services/account/useUpdateCard.test.tsx
@@ -6,6 +6,8 @@ import React from 'react'
import { MemoryRouter, Route } from 'react-router-dom'
import { type Mock } from 'vitest'
+import { Plans } from 'shared/utils/billing'
+
import { useUpdateCard } from './useUpdateCard'
const mocks = vi.hoisted(() => ({
@@ -42,7 +44,7 @@ const accountDetails = {
baseUnitPrice: 12,
benefits: ['Configurable # of users', 'Unlimited repos'],
quantity: 5,
- value: 'users-inappm',
+ value: Plans.USERS_PR_INAPPM,
},
activatedUserCount: 2,
inactiveUserCount: 1,
diff --git a/src/services/account/useUpgradePlan.test.tsx b/src/services/account/useUpgradePlan.test.tsx
index 5e11b16427..342edb8cd1 100644
--- a/src/services/account/useUpgradePlan.test.tsx
+++ b/src/services/account/useUpgradePlan.test.tsx
@@ -5,6 +5,8 @@ import { setupServer } from 'msw/node'
import { MemoryRouter, Route } from 'react-router-dom'
import type { MockInstance } from 'vitest'
+import { Plans } from 'shared/utils/billing'
+
import { useUpgradePlan } from './useUpgradePlan'
const mocks = vi.hoisted(() => ({
@@ -41,7 +43,7 @@ const accountDetails = {
baseUnitPrice: 12,
benefits: ['Configurable # of users', 'Unlimited repos'],
quantity: 5,
- value: 'users-inappm',
+ value: Plans.USERS_PR_INAPPM,
},
activatedUserCount: 2,
inactiveUserCount: 1,
@@ -113,7 +115,7 @@ describe('useUpgradePlan', () => {
result.current.mutate({
seats: 12,
- newPlan: 'users-pr-inappy',
+ newPlan: Plans.USERS_PR_INAPPY,
})
await waitFor(() => {
@@ -147,7 +149,7 @@ describe('useUpgradePlan', () => {
result.current.mutate({
seats: 12,
- newPlan: 'users-pr-inappy',
+ newPlan: Plans.USERS_PR_INAPPY,
})
await waitFor(() => expect(redirectToCheckout).not.toHaveBeenCalled())
diff --git a/src/services/charts/useSunburstCoverage.ts b/src/services/charts/useSunburstCoverage.ts
index 3d1b39a53a..4ab91e054e 100644
--- a/src/services/charts/useSunburstCoverage.ts
+++ b/src/services/charts/useSunburstCoverage.ts
@@ -1,10 +1,11 @@
import { useQuery } from '@tanstack/react-query'
import Api from 'shared/api'
+import { Provider } from 'shared/api/helpers'
import { providerToInternalProvider } from 'shared/utils'
interface SunburstCoverageArgs {
- provider: string
+ provider: Provider
owner: string
repo: string
query?: {
diff --git a/src/services/pull/usePull.tsx b/src/services/pull/usePull.tsx
index 36a09b487f..e11321b80c 100644
--- a/src/services/pull/usePull.tsx
+++ b/src/services/pull/usePull.tsx
@@ -186,7 +186,6 @@ export type PullSchemaType = z.infer
const RepositorySchema = z.object({
defaultBranch: z.string().nullable(),
- private: z.boolean(),
__typename: z.literal('Repository'),
pull: PullSchema.nullable(),
})
@@ -194,7 +193,6 @@ const RepositorySchema = z.object({
const RequestSchema = z.object({
owner: z
.object({
- isCurrentUserPartOfOrg: z.boolean(),
repository: z.discriminatedUnion('__typename', [
RepositorySchema,
RepoNotFoundErrorSchema,
@@ -216,7 +214,6 @@ const query = `query Pull(
__typename
... on Repository {
defaultBranch
- private
pull(id: $pullId) {
behindBy
behindByCommit
diff --git a/src/shared/GlobalBanners/GitHubRateLimitExceeded/GitHubRateLimitExceededBanner.tsx b/src/shared/GlobalBanners/GitHubRateLimitExceeded/GitHubRateLimitExceededBanner.tsx
index a932dca1f4..fb44f94f5c 100644
--- a/src/shared/GlobalBanners/GitHubRateLimitExceeded/GitHubRateLimitExceededBanner.tsx
+++ b/src/shared/GlobalBanners/GitHubRateLimitExceeded/GitHubRateLimitExceededBanner.tsx
@@ -1,11 +1,12 @@
import { useParams } from 'react-router-dom'
+import { Provider } from 'shared/api/helpers'
import { providerToName } from 'shared/utils/provider'
import A from 'ui/A'
import { Alert } from 'ui/Alert'
const GitHubRateLimitExceededBanner = () => {
- const { provider } = useParams<{ provider: string }>()
+ const { provider } = useParams<{ provider: Provider }>()
const isGh = providerToName(provider) === 'Github'
if (!isGh) return null
diff --git a/src/shared/GlobalTopBanners/ProPlanFeedbackBanner/ProPlanFeedbackBanner.test.tsx b/src/shared/GlobalTopBanners/ProPlanFeedbackBanner/ProPlanFeedbackBanner.test.tsx
index e5183063b4..696ed03121 100644
--- a/src/shared/GlobalTopBanners/ProPlanFeedbackBanner/ProPlanFeedbackBanner.test.tsx
+++ b/src/shared/GlobalTopBanners/ProPlanFeedbackBanner/ProPlanFeedbackBanner.test.tsx
@@ -8,6 +8,7 @@ import { MemoryRouter, Route } from 'react-router-dom'
import { TrialStatuses } from 'services/account'
import { TierNames } from 'services/tier'
+import { Plans } from 'shared/utils/billing'
import ProPlanFeedbackBanner from './ProPlanFeedbackBanner'
@@ -27,7 +28,7 @@ const mockTrialData = {
billingRate: 'monthly',
marketingName: 'Users Basic',
monthlyUploadLimit: 250,
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
trialStatus: TrialStatuses.EXPIRED,
trialStartDate: '2023-01-01T08:55:25',
trialEndDate: '2023-01-10T08:55:25',
@@ -42,7 +43,7 @@ const mockTrialData = {
billingRate: 'monthly',
marketingName: 'Users Basic',
monthlyUploadLimit: 250,
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
},
}
diff --git a/src/shared/GlobalTopBanners/RequestInstallBanner/RequestInstallBanner.tsx b/src/shared/GlobalTopBanners/RequestInstallBanner/RequestInstallBanner.tsx
index 81efca5f72..7b71671920 100644
--- a/src/shared/GlobalTopBanners/RequestInstallBanner/RequestInstallBanner.tsx
+++ b/src/shared/GlobalTopBanners/RequestInstallBanner/RequestInstallBanner.tsx
@@ -4,6 +4,7 @@ import { useParams, useRouteMatch } from 'react-router-dom'
import config from 'config'
import { useLocationParams } from 'services/navigation'
+import { Provider } from 'shared/api/helpers'
import AppInstallModal from 'shared/AppInstallModal'
import { providerToName } from 'shared/utils'
import Button from 'ui/Button'
@@ -13,7 +14,7 @@ import TopBanner, { saveToLocalStorage } from 'ui/TopBanner'
const APP_INSTALL_BANNER_KEY = 'request-install-banner'
interface URLParams {
- provider: string
+ provider: Provider
}
const defaultQueryParams = {
diff --git a/src/shared/GlobalTopBanners/TrialBanner/TrialBanner.test.tsx b/src/shared/GlobalTopBanners/TrialBanner/TrialBanner.test.tsx
index 3208eb2638..40dd200e9a 100644
--- a/src/shared/GlobalTopBanners/TrialBanner/TrialBanner.test.tsx
+++ b/src/shared/GlobalTopBanners/TrialBanner/TrialBanner.test.tsx
@@ -9,6 +9,7 @@ import { MemoryRouter, Route } from 'react-router-dom'
import config from 'config'
import { TrialStatuses } from 'services/account'
+import { Plans } from 'shared/utils/billing'
import TrialBanner from './TrialBanner'
@@ -16,7 +17,7 @@ vi.mock('config')
const proPlanMonth = {
marketingName: 'Pro Team',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -33,7 +34,7 @@ const proPlanMonth = {
const trialPlan = {
marketingName: 'Trial Team',
- value: 'users-trial',
+ value: Plans.USERS_TRIAL,
billingRate: 'monthly',
baseUnitPrice: 12,
benefits: [
@@ -50,7 +51,7 @@ const trialPlan = {
const basicPlan = {
marketingName: 'Basic',
- value: 'users-basic',
+ value: Plans.USERS_BASIC,
billingRate: null,
baseUnitPrice: 0,
benefits: [
diff --git a/src/shared/api/helpers.ts b/src/shared/api/helpers.ts
index 692e810c22..8513756f5f 100644
--- a/src/shared/api/helpers.ts
+++ b/src/shared/api/helpers.ts
@@ -53,7 +53,7 @@ export const AllProvidersArray = [
'bitbucket_server',
] as const
type AllProviders = typeof AllProvidersArray
-type Provider = AllProviders[number]
+export type Provider = AllProviders[number]
export const ProviderCookieKeyMapping = {
gh: 'github-token',
diff --git a/src/shared/plan/BenefitList/BenefitList.tsx b/src/shared/plan/BenefitList/BenefitList.tsx
index bfa1d99f44..1168dceac2 100644
--- a/src/shared/plan/BenefitList/BenefitList.tsx
+++ b/src/shared/plan/BenefitList/BenefitList.tsx
@@ -5,7 +5,7 @@ function BenefitList({
iconName,
iconColor,
}: {
- benefits: string[]
+ benefits?: string[]
iconName: string
iconColor?: string
}) {
diff --git a/src/shared/utils/billing.test.js b/src/shared/utils/billing.test.ts
similarity index 85%
rename from src/shared/utils/billing.test.js
rename to src/shared/utils/billing.test.ts
index e94d5da10a..61f56a19bd 100644
--- a/src/shared/utils/billing.test.js
+++ b/src/shared/utils/billing.test.ts
@@ -1,7 +1,5 @@
import { renderHook } from '@testing-library/react'
-import { useFlags } from 'shared/featureFlags'
-
import {
canApplySentryUpgrade,
EnterprisePlans,
@@ -23,20 +21,32 @@ import {
isTeamPlan,
isTrialPlan,
lastTwoDigits,
+ Plan,
Plans,
shouldDisplayTeamCard,
useProPlans,
} from './billing'
-vi.mock('shared/featureFlags')
+const mocks = vi.hoisted(() => ({
+ useFlags: vi.fn(),
+}))
+
+vi.mock('shared/featureFlags', async () => {
+ const actual = await vi.importActual('shared/featureFlags')
+ return {
+ ...actual,
+ useFlags: mocks.useFlags,
+ }
+})
function getPlans() {
return [
{
marketingName: 'Basic',
- value: 'users-free',
+ value: Plans.USERS_FREE,
billingRate: null,
baseUnitPrice: 0,
+ monthlyUploadLimit: null,
benefits: [
'Up to 5 users',
'Unlimited public repositories',
@@ -45,9 +55,10 @@ function getPlans() {
},
{
marketingName: 'Pro Team',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billingRate: 'monthly',
baseUnitPrice: 12,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -57,9 +68,10 @@ function getPlans() {
},
{
marketingName: 'Pro Team',
- value: 'users-pr-inappy',
+ value: Plans.USERS_PR_INAPPY,
billingRate: 'annually',
baseUnitPrice: 10,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -69,9 +81,10 @@ function getPlans() {
},
{
marketingName: 'Pro Team',
- value: 'users-enterprisem',
+ value: Plans.USERS_ENTERPRISEM,
billingRate: 'monthly',
baseUnitPrice: 12,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -81,9 +94,10 @@ function getPlans() {
},
{
marketingName: 'Pro Team',
- value: 'users-enterprisey',
+ value: Plans.USERS_ENTERPRISEY,
billingRate: 'annually',
baseUnitPrice: 10,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -93,9 +107,10 @@ function getPlans() {
},
{
marketingName: 'Sentry Pro Team',
- value: 'users-sentrym',
+ value: Plans.USERS_SENTRYM,
billingRate: 'monthly',
baseUnitPrice: 12,
+ monthlyUploadLimit: null,
benefits: [
'Includes 5 seats',
'Unlimited public repositories',
@@ -106,9 +121,10 @@ function getPlans() {
},
{
marketingName: 'Sentry Pro Team',
- value: 'users-sentryy',
+ value: Plans.USERS_SENTRYY,
billingRate: 'annually',
baseUnitPrice: 10,
+ monthlyUploadLimit: null,
benefits: [
'Includes 5 seats',
'Unlimited public repositories',
@@ -119,9 +135,10 @@ function getPlans() {
},
{
marketingName: 'Team',
- value: 'users-teamm',
+ value: Plans.USERS_TEAMM,
billingRate: 'monthly',
baseUnitPrice: 6,
+ monthlyUploadLimit: null,
benefits: [
'Up to 10 users',
'Unlimited repositories',
@@ -132,9 +149,10 @@ function getPlans() {
},
{
marketingName: 'Team',
- value: 'users-teamy',
+ value: Plans.USERS_TEAMY,
billingRate: 'yearly',
baseUnitPrice: 5,
+ monthlyUploadLimit: null,
benefits: [
'Up to 10 users',
'Unlimited repositories',
@@ -158,11 +176,8 @@ describe('isFreePlan', () => {
})
it('Defaults to false otherwise', () => {
- expect(isFreePlan('users-pro')).toBe(false)
- expect(isFreePlan('rable rable')).toBe(false)
+ expect(isFreePlan('users-inappy')).toBe(false)
expect(isFreePlan(undefined)).toBe(false)
- expect(isFreePlan(12345)).toBe(false)
- expect(isFreePlan({})).toBe(false)
})
})
@@ -176,9 +191,10 @@ describe('shouldDisplayTeamCard', () => {
const plans = [
{
marketingName: 'Pro Team',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billingRate: 'monthly',
baseUnitPrice: 12,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -188,9 +204,10 @@ describe('shouldDisplayTeamCard', () => {
},
{
marketingName: 'Pro Team',
- value: 'users-pr-inappy',
+ value: Plans.USERS_PR_INAPPY,
billingRate: 'annually',
baseUnitPrice: 10,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -215,17 +232,14 @@ describe('isEnterprisePlans', () => {
})
it('defaults to false otherwise', () => {
- expect(isEnterprisePlan('users-pro')).toBe(false)
- expect(isEnterprisePlan('rable rable')).toBe(false)
+ expect(isEnterprisePlan('users-inappy')).toBe(false)
expect(isEnterprisePlan(undefined)).toBe(false)
- expect(isEnterprisePlan(12345)).toBe(false)
- expect(isEnterprisePlan({})).toBe(false)
})
})
describe('useProPlans', () => {
- function setup(flagValue) {
- useFlags.mockReturnValue({
+ function setup(flagValue: boolean) {
+ mocks.useFlags.mockReturnValue({
enterpriseCloudPlanSupport: flagValue,
})
}
@@ -241,9 +255,10 @@ describe('useProPlans', () => {
expect(result.current).toEqual({
proPlanMonth: {
marketingName: 'Pro Team',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billingRate: 'monthly',
baseUnitPrice: 12,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -253,9 +268,10 @@ describe('useProPlans', () => {
},
proPlanYear: {
marketingName: 'Pro Team',
- value: 'users-pr-inappy',
+ value: Plans.USERS_PR_INAPPY,
billingRate: 'annually',
baseUnitPrice: 10,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -277,9 +293,10 @@ describe('useProPlans', () => {
expect(result.current).toEqual({
proPlanMonth: {
marketingName: 'Pro Team',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billingRate: 'monthly',
baseUnitPrice: 12,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -289,9 +306,10 @@ describe('useProPlans', () => {
},
proPlanYear: {
marketingName: 'Pro Team',
- value: 'users-pr-inappy',
+ value: Plans.USERS_PR_INAPPY,
billingRate: 'annually',
baseUnitPrice: 10,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -314,6 +332,7 @@ describe('formatNumberToUSD', () => {
describe('formatTimestampToCalendarDate', () => {
it('formats into calendar date', () => {
+ // @ts-expect-error
const value = formatTimestampToCalendarDate('1660000000')
expect(value).toBe('August 8, 2022')
@@ -334,6 +353,7 @@ describe('lastTwoDigits', () => {
})
it('return null when null', () => {
+ // @ts-expect-error
const value = lastTwoDigits(null)
expect(value).toBe(null)
@@ -343,16 +363,9 @@ describe('lastTwoDigits', () => {
describe('getNextBillingDate', () => {
describe('there is a valid timestamp', () => {
it('returns formatted timestamp', () => {
- const value = getNextBillingDate({})
-
- expect(value).toBeNull()
- })
- })
-
- describe('there is no timestamp', () => {
- it('returns null', () => {
const value = getNextBillingDate({
subscriptionDetail: {
+ // @ts-expect-error
latestInvoice: {
periodEnd: 1660000000,
},
@@ -362,6 +375,15 @@ describe('getNextBillingDate', () => {
expect(value).toBe('August 8th, 2022')
})
})
+
+ describe('there is no timestamp', () => {
+ it('returns null', () => {
+ // @ts-expect-error
+ const value = getNextBillingDate({})
+
+ expect(value).toBeNull()
+ })
+ })
})
describe('isAnnualPlan', () => {
@@ -386,11 +408,8 @@ describe('isAnnualPlan', () => {
})
it('defaults to false otherwise', () => {
- expect(isAnnualPlan('users-pro')).toBe(false)
- expect(isAnnualPlan('rable rable')).toBe(false)
+ expect(isAnnualPlan('users-inappm')).toBe(false)
expect(isAnnualPlan(undefined)).toBe(false)
- expect(isAnnualPlan(12345)).toBe(false)
- expect(isAnnualPlan({})).toBe(false)
})
})
@@ -411,11 +430,8 @@ describe('isMonthlyPlan', () => {
})
it('defaults to false otherwise', () => {
- expect(isMonthlyPlan('users-pro')).toBe(false)
- expect(isMonthlyPlan('rable rable')).toBe(false)
+ expect(isMonthlyPlan('users-inappy')).toBe(false)
expect(isMonthlyPlan(undefined)).toBe(false)
- expect(isMonthlyPlan(12345)).toBe(false)
- expect(isMonthlyPlan({})).toBe(false)
})
})
@@ -431,11 +447,8 @@ describe('isSentryPlan', () => {
})
it('Defaults to false otherwise', () => {
- expect(isSentryPlan('users-pro')).toBe(false)
- expect(isSentryPlan('rable rable')).toBe(false)
+ expect(isSentryPlan('users-inappy')).toBe(false)
expect(isSentryPlan(undefined)).toBe(false)
- expect(isSentryPlan(12345)).toBe(false)
- expect(isSentryPlan({})).toBe(false)
})
})
@@ -460,10 +473,8 @@ describe('isPaidPlan', () => {
})
it('defaults to false otherwise', () => {
- expect(isPaidPlan('rable rable')).toBe(false)
+ expect(isPaidPlan('users-free')).toBe(false)
expect(isPaidPlan(undefined)).toBe(false)
- expect(isPaidPlan(12345)).toBe(false)
- expect(isPaidPlan({})).toBe(false)
})
})
@@ -474,9 +485,10 @@ describe('findSentryPlans', () => {
const expectedResult = {
marketingName: 'Sentry Pro Team',
- value: 'users-sentrym',
+ value: Plans.USERS_SENTRYM,
billingRate: 'monthly',
baseUnitPrice: 12,
+ monthlyUploadLimit: null,
benefits: [
'Includes 5 seats',
'Unlimited public repositories',
@@ -495,9 +507,10 @@ describe('findSentryPlans', () => {
const expectedResult = {
marketingName: 'Sentry Pro Team',
- value: 'users-sentryy',
+ value: Plans.USERS_SENTRYY,
billingRate: 'annually',
baseUnitPrice: 10,
+ monthlyUploadLimit: null,
benefits: [
'Includes 5 seats',
'Unlimited public repositories',
@@ -518,9 +531,10 @@ describe('findProPlans', () => {
const expectedResult = {
marketingName: 'Pro Team',
- value: 'users-pr-inappm',
+ value: Plans.USERS_PR_INAPPM,
billingRate: 'monthly',
baseUnitPrice: 12,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -538,9 +552,10 @@ describe('findProPlans', () => {
const expectedResult = {
marketingName: 'Pro Team',
- value: 'users-pr-inappy',
+ value: Plans.USERS_PR_INAPPY,
billingRate: 'annually',
baseUnitPrice: 10,
+ monthlyUploadLimit: null,
benefits: [
'Configureable # of users',
'Unlimited public repositories',
@@ -560,9 +575,10 @@ describe('findTeamPlans', () => {
const expectedResult = {
marketingName: 'Team',
- value: 'users-teamm',
+ value: Plans.USERS_TEAMM,
billingRate: 'monthly',
baseUnitPrice: 6,
+ monthlyUploadLimit: null,
benefits: [
'Up to 10 users',
'Unlimited repositories',
@@ -581,9 +597,10 @@ describe('findTeamPlans', () => {
const expectedResult = {
marketingName: 'Team',
- value: 'users-teamy',
+ value: Plans.USERS_TEAMY,
billingRate: 'yearly',
baseUnitPrice: 5,
+ monthlyUploadLimit: null,
benefits: [
'Up to 10 users',
'Unlimited repositories',
@@ -601,7 +618,7 @@ describe('canApplySentryUpgrade', () => {
it('returns true when list contains monthly plan', () => {
const result = canApplySentryUpgrade({
plan: Plans.USERS_PR_INAPPM,
- plans: [{ value: 'users-sentrym' }],
+ plans: [{ value: Plans.USERS_SENTRYM }] as Plan[],
})
expect(result).toBeTruthy()
@@ -610,7 +627,7 @@ describe('canApplySentryUpgrade', () => {
it('returns true when list contains annual plan', () => {
const result = canApplySentryUpgrade({
plan: Plans.USERS_PR_INAPPM,
- plans: [{ value: 'users-sentryy' }],
+ plans: [{ value: Plans.USERS_SENTRYY }] as Plan[],
})
expect(result).toBeTruthy()
@@ -619,7 +636,7 @@ describe('canApplySentryUpgrade', () => {
it('returns false when plans are not in list', () => {
const result = canApplySentryUpgrade({
plan: Plans.USERS_PR_INAPPM,
- plans: [{ value: 'users-free' }],
+ plans: [{ value: Plans.USERS_FREE }] as Plan[],
})
expect(result).toBeFalsy()
@@ -628,7 +645,7 @@ describe('canApplySentryUpgrade', () => {
it('returns false when user has enterprise plan', () => {
const result = canApplySentryUpgrade({
plan: Plans.USERS_ENTERPRISEM,
- plans: [{ value: 'users-sentryy' }],
+ plans: [{ value: Plans.USERS_SENTRYY }] as Plan[],
})
expect(result).toBeFalsy()
@@ -646,12 +663,6 @@ describe('isBasicPlan', () => {
expect(isBasicPlan(Plans.USERS_ENTERPRISEM)).toBeFalsy()
expect(isBasicPlan(Plans.USERS_SENTRYM)).toBeFalsy()
})
-
- it('returns false when plan is not a string', () => {
- expect(isBasicPlan(123)).toBeFalsy()
- expect(isBasicPlan({})).toBeFalsy()
- expect(isBasicPlan([])).toBeFalsy()
- })
})
describe('isTeamPlan', () => {
@@ -667,12 +678,6 @@ describe('isTeamPlan', () => {
expect(isTeamPlan(Plans.USERS_ENTERPRISEM)).toBeFalsy()
expect(isTeamPlan(Plans.USERS_SENTRYM)).toBeFalsy()
})
-
- it('returns false when plan is not a string', () => {
- expect(isTeamPlan(123)).toBeFalsy()
- expect(isTeamPlan({})).toBeFalsy()
- expect(isTeamPlan([])).toBeFalsy()
- })
})
describe('isTrialPlan', () => {
@@ -687,12 +692,6 @@ describe('isTrialPlan', () => {
expect(isTrialPlan(Plans.USERS_SENTRYM)).toBeFalsy()
expect(isTrialPlan(Plans.USERS_BASIC)).toBeFalsy()
})
-
- it('returns false when plan is not a string', () => {
- expect(isTrialPlan(123)).toBeFalsy()
- expect(isTrialPlan({})).toBeFalsy()
- expect(isTrialPlan([])).toBeFalsy()
- })
})
describe('isProPlan', () => {
@@ -709,12 +708,6 @@ describe('isProPlan', () => {
expect(isProPlan(Plans.USERS_ENTERPRISEM)).toBeFalsy()
expect(isProPlan(Plans.USERS_BASIC)).toBeFalsy()
})
-
- it('returns false when plan is not a string', () => {
- expect(isProPlan(123)).toBeFalsy()
- expect(isProPlan({})).toBeFalsy()
- expect(isProPlan([])).toBeFalsy()
- })
})
describe('isCodecovProPlan', () => {
@@ -728,10 +721,4 @@ describe('isCodecovProPlan', () => {
expect(isCodecovProPlan(Plans.USERS_SENTRYM)).toBeFalsy()
expect(isCodecovProPlan(Plans.USERS_BASIC)).toBeFalsy()
})
-
- it('returns false when plan is not a string', () => {
- expect(isCodecovProPlan(123)).toBeFalsy()
- expect(isCodecovProPlan({})).toBeFalsy()
- expect(isCodecovProPlan([])).toBeFalsy()
- })
})
diff --git a/src/shared/utils/billing.js b/src/shared/utils/billing.ts
similarity index 71%
rename from src/shared/utils/billing.js
rename to src/shared/utils/billing.ts
index 814a0c5163..259a1fcdb4 100644
--- a/src/shared/utils/billing.js
+++ b/src/shared/utils/billing.ts
@@ -2,10 +2,12 @@ import { format, fromUnixTime } from 'date-fns'
import isArray from 'lodash/isArray'
import isString from 'lodash/isString'
import isUndefined from 'lodash/isUndefined'
+import { z } from 'zod'
+import { AccountDetailsSchema } from 'services/account'
import { useFlags } from 'shared/featureFlags'
-export const Plans = Object.freeze({
+export const Plans = {
USERS_FREE: 'users-free',
USERS_BASIC: 'users-basic',
USERS_TRIAL: 'users-trial',
@@ -19,48 +21,61 @@ export const Plans = Object.freeze({
USERS_TEAMY: 'users-teamy',
USERS_ENTERPRISEM: 'users-enterprisem',
USERS_ENTERPRISEY: 'users-enterprisey',
-})
+} as const
+
+export type PlanName = (typeof Plans)[keyof typeof Plans]
+
+export interface Plan {
+ baseUnitPrice: number
+ benefits: string[]
+ billingRate: string | null
+ marketingName: string
+ value: PlanName
+ monthlyUploadLimit: number | null
+ quantity?: number
+}
export const EnterprisePlans = Object.freeze({
USERS_ENTERPRISEM: 'users-enterprisem',
USERS_ENTERPRISEY: 'users-enterprisey',
})
-export function isEnterprisePlan(plan) {
+export function isEnterprisePlan(plan?: PlanName | null) {
if (isString(plan)) {
- return Object.values(EnterprisePlans).includes(plan)
+ return (Object.values(EnterprisePlans) as string[]).includes(plan)
}
+
return false
}
-export function isFreePlan(plan) {
+export function isFreePlan(plan?: PlanName | null) {
if (isString(plan)) {
if (plan === Plans.USERS_BASIC || plan === Plans.USERS_FREE) return true
}
return false
}
-export function isTeamPlan(plan) {
+export function isTeamPlan(plan?: PlanName | null) {
if (isString(plan)) {
if (plan === Plans.USERS_TEAMM || plan === Plans.USERS_TEAMY) return true
}
return false
}
-export function isBasicPlan(plan) {
+export function isBasicPlan(plan?: PlanName) {
if (isString(plan)) {
return plan === Plans.USERS_BASIC
}
return false
}
-export function isPaidPlan(plan) {
+export function isPaidPlan(plan?: PlanName | null) {
if (isString(plan)) {
return isAnnualPlan(plan) || isMonthlyPlan(plan)
}
return false
}
-export function isMonthlyPlan(plan) {
+export function isMonthlyPlan(plan?: PlanName | null) {
if (isString(plan)) {
return (
plan === Plans.USERS_INAPP ||
@@ -73,7 +88,7 @@ export function isMonthlyPlan(plan) {
return false
}
-export function isAnnualPlan(plan) {
+export function isAnnualPlan(plan?: PlanName | null) {
if (isString(plan)) {
return (
plan === Plans.USERS_INAPPY ||
@@ -86,28 +101,28 @@ export function isAnnualPlan(plan) {
return false
}
-export function isSentryPlan(plan) {
+export function isSentryPlan(plan?: PlanName | null) {
if (isString(plan)) {
return plan === Plans.USERS_SENTRYM || plan === Plans.USERS_SENTRYY
}
return false
}
-export function isCodecovProPlan(plan) {
+export function isCodecovProPlan(plan?: PlanName | null) {
if (isString(plan)) {
return plan === Plans.USERS_PR_INAPPM || plan === Plans.USERS_PR_INAPPY
}
return false
}
-export function isProPlan(plan) {
+export function isProPlan(plan?: PlanName | null) {
if (isString(plan)) {
return isSentryPlan(plan) || isCodecovProPlan(plan)
}
return false
}
-export function isTrialPlan(plan) {
+export function isTrialPlan(plan?: PlanName | null) {
if (isString(plan)) {
return plan === Plans.USERS_TRIAL
}
@@ -120,7 +135,7 @@ export const CollectionMethods = Object.freeze({
AUTOMATICALLY_CHARGED_METHOD: 'charge_automatically',
})
-export function useProPlans({ plans }) {
+export function useProPlans({ plans }: { plans?: Plan[] | null }) {
const { enterpriseCloudPlanSupport } = useFlags({
enterpriseCloudPlanSupport: true,
})
@@ -147,7 +162,7 @@ export function useProPlans({ plans }) {
}
}
-export const findProPlans = ({ plans }) => {
+export const findProPlans = ({ plans }: { plans?: Plan[] | null }) => {
const proPlanMonth = plans?.find(
(plan) => plan.value === Plans.USERS_PR_INAPPM
)
@@ -161,7 +176,7 @@ export const findProPlans = ({ plans }) => {
}
}
-export const findSentryPlans = ({ plans }) => {
+export const findSentryPlans = ({ plans }: { plans?: Plan[] | null }) => {
const sentryPlanMonth = plans?.find(
(plan) => plan.value === Plans.USERS_SENTRYM
)
@@ -175,7 +190,7 @@ export const findSentryPlans = ({ plans }) => {
}
}
-export const findTeamPlans = ({ plans }) => {
+export const findTeamPlans = ({ plans }: { plans?: Plan[] | null }) => {
const teamPlanMonth = plans?.find((plan) => plan.value === Plans.USERS_TEAMM)
const teamPlanYear = plans?.find((plan) => plan.value === Plans.USERS_TEAMY)
@@ -185,7 +200,13 @@ export const findTeamPlans = ({ plans }) => {
}
}
-export const canApplySentryUpgrade = ({ plan, plans }) => {
+export const canApplySentryUpgrade = ({
+ plan,
+ plans,
+}: {
+ plan?: PlanName
+ plans?: Plan[] | null
+}) => {
if (isEnterprisePlan(plan) || !isArray(plans)) {
return false
}
@@ -196,26 +217,30 @@ export const canApplySentryUpgrade = ({ plan, plans }) => {
)
}
-export const shouldDisplayTeamCard = ({ plans }) => {
+export const shouldDisplayTeamCard = ({ plans }: { plans?: Plan[] | null }) => {
const { teamPlanMonth, teamPlanYear } = findTeamPlans({ plans })
return !isUndefined(teamPlanMonth) && !isUndefined(teamPlanYear)
}
-export const formatNumberToUSD = (value) =>
+export const formatNumberToUSD = (value: number) =>
Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
currencyDisplay: 'narrowSymbol',
}).format(value)
-export function getNextBillingDate(accountDetails) {
+export function getNextBillingDate(
+ accountDetails?: z.infer | null
+) {
const timestamp = accountDetails?.subscriptionDetail?.latestInvoice?.periodEnd
return timestamp ? format(fromUnixTime(timestamp), 'MMMM do, yyyy') : null
}
// TODO: This is now the preferred format for dates, please use this over any other formatting
-export function formatTimestampToCalendarDate(timestamp) {
+export function formatTimestampToCalendarDate(
+ timestamp: number | null | undefined
+) {
if (!timestamp) {
return null
}
@@ -226,10 +251,11 @@ export function formatTimestampToCalendarDate(timestamp) {
day: 'numeric',
year: 'numeric',
}
+ // @ts-expect-error Complaining about year not being type 'numeric' | '2-digit' | 'undefined'
return new Intl.DateTimeFormat('en-US', options).format(date)
}
-export function lastTwoDigits(value) {
+export function lastTwoDigits(value: number | string) {
if (typeof value === 'number' || typeof value === 'string') {
return value.toString().slice(-2)
}
diff --git a/src/shared/utils/provider.test.js b/src/shared/utils/provider.test.ts
similarity index 70%
rename from src/shared/utils/provider.test.js
rename to src/shared/utils/provider.test.ts
index 5a7e284b8e..18d2328233 100644
--- a/src/shared/utils/provider.test.js
+++ b/src/shared/utils/provider.test.ts
@@ -3,8 +3,6 @@ import config from 'config'
import {
getProviderCommitURL,
getProviderPullURL,
- providerFeedback,
- providerImage,
providerToInternalProvider,
providerToName,
} from './provider'
@@ -62,6 +60,7 @@ describe('providerToName', () => {
describe('when called with BitBucket', () => {
it('returns BitBucket', () => {
+ // @ts-expect-error
expect(providerToName('BitBucket')).toBe('BitBucket')
})
})
@@ -85,88 +84,10 @@ describe('providerToName', () => {
})
})
-describe('providerImage', () => {
- describe('when called for Github', () => {
- it('returns correct logo url', () => {
- expect(providerImage('Github')).toMatch(/github-icon.svg/)
- })
- })
- describe('when called for Gitlab', () => {
- it('returns correct logo url', () => {
- expect(providerImage('Gitlab')).toMatch(/gitlab-icon.svg/)
- })
- })
- describe('when called for BitBucket', () => {
- it('returns correct logo url', () => {
- expect(providerImage('BitBucket')).toMatch(/bitbucket-icon.svg/)
- })
- })
- describe('when called for Github Enterprise', () => {
- it('returns correct logo url', () => {
- expect(providerImage('github_enterprise')).toMatch(/github-icon.svg/)
- })
- })
- describe('when called for Gitlab Enterprise', () => {
- it('returns correct logo url', () => {
- expect(providerImage('gitlab_enterprise')).toMatch(/gitlab-icon.svg/)
- })
- })
- describe('when called for BitBucket Server', () => {
- it('returns correct logo url', () => {
- expect(providerImage('bitbucket_server')).toMatch(/bitbucket-icon.svg/)
- })
- })
-})
-
-describe('providerFeedback', () => {
- describe('when called for Github', () => {
- it('returns correct url', () => {
- expect(providerFeedback('Github')).toEqual(
- 'https://github.com/codecov/Codecov-user-feedback/issues/1'
- )
- })
- })
- describe('when called for Gitlab', () => {
- it('returns correct url', () => {
- expect(providerFeedback('Gitlab')).toEqual(
- 'https://gitlab.com/codecov-open-source/codecov-user-feedback/-/issues/1'
- )
- })
- })
- describe('when called for BitBucket', () => {
- it('returns correct url', () => {
- expect(providerFeedback('BitBucket')).toEqual(
- 'https://bitbucket.org/kylemann/codecov/issues/1/wed-love-your-feedback'
- )
- })
- })
- describe('when called for Github Enterprise', () => {
- it('returns correct url', () => {
- expect(providerFeedback('github_enterprise')).toEqual(
- 'https://github.com/codecov/Codecov-user-feedback/issues/1'
- )
- })
- })
- describe('when called for Gitlab Enterprise', () => {
- it('returns correct url', () => {
- expect(providerFeedback('gitlab_enterprise')).toEqual(
- 'https://gitlab.com/codecov-open-source/codecov-user-feedback/-/issues/1'
- )
- })
- })
- describe('when called for BitBucket Server', () => {
- it('returns correct url', () => {
- expect(providerFeedback('bitbucket_server')).toEqual(
- 'https://bitbucket.org/kylemann/codecov/issues/1/wed-love-your-feedback'
- )
- })
- })
-})
-
const repo = 'python'
const owner = 'codecov'
const commit = '12de'
-const pullId = 'aebf'
+const pullId = 12
describe('getProviderCommitURL', () => {
it('return gitlab commit URL', () => {
@@ -210,38 +131,38 @@ describe('getProviderCommitURL', () => {
describe('getProviderPullURL', () => {
it('return gitlab PR URL', () => {
expect(getProviderPullURL({ provider: 'gl', owner, repo, pullId })).toBe(
- 'https://gitlab.com/codecov/python/-/merge_requests/aebf'
+ 'https://gitlab.com/codecov/python/-/merge_requests/12'
)
})
it('return github PR URL', () => {
expect(getProviderPullURL({ provider: 'gh', owner, repo, pullId })).toBe(
- 'https://github.com/codecov/python/pull/aebf'
+ 'https://github.com/codecov/python/pull/12'
)
})
it('return bb PR URL', () => {
expect(getProviderPullURL({ provider: 'bb', owner, repo, pullId })).toBe(
- 'https://bitbucket.org/codecov/python/pull-requests/aebf'
+ 'https://bitbucket.org/codecov/python/pull-requests/12'
)
})
it('return ghe PR URL', () => {
config.GHE_URL = 'https://github.mycompany.org'
expect(getProviderPullURL({ provider: 'ghe', owner, repo, pullId })).toBe(
- 'https://github.mycompany.org/codecov/python/pull/aebf'
+ 'https://github.mycompany.org/codecov/python/pull/12'
)
})
it('return gle PR URL', () => {
config.GLE_URL = 'https://gitlab.mycompany.org'
expect(getProviderPullURL({ provider: 'gle', owner, repo, pullId })).toBe(
- 'https://gitlab.mycompany.org/codecov/python/-/merge_requests/aebf'
+ 'https://gitlab.mycompany.org/codecov/python/-/merge_requests/12'
)
})
it('return bbs PR URL', () => {
config.BBS_URL = 'https://bitbucket.mycompany.org'
expect(getProviderPullURL({ provider: 'bbs', owner, repo, pullId })).toBe(
- 'https://bitbucket.mycompany.org/codecov/python/pull-requests/aebf'
+ 'https://bitbucket.mycompany.org/codecov/python/pull-requests/12'
)
})
})
@@ -297,6 +218,7 @@ describe('providerToInternalProvider', () => {
describe('when called with BitBucket', () => {
it('returns bitbucket', () => {
+ // @ts-expect-error
expect(providerToInternalProvider('BitBucket')).toBe('bitbucket')
})
})
diff --git a/src/shared/utils/provider.js b/src/shared/utils/provider.ts
similarity index 57%
rename from src/shared/utils/provider.js
rename to src/shared/utils/provider.ts
index 654ebe3ec3..56c2d3499c 100644
--- a/src/shared/utils/provider.js
+++ b/src/shared/utils/provider.ts
@@ -1,11 +1,9 @@
/* eslint-disable camelcase */
import config from 'config'
-import bitbucketLogo from 'assets/providers/bitbucket-icon.svg'
-import githubLogo from 'assets/providers/github-icon.svg'
-import gitlabLogo from 'assets/providers/gitlab-icon.svg'
+import { Provider } from 'shared/api/helpers'
-export function providerToName(provider) {
+export function providerToName(provider: Provider) {
return {
gh: 'Github',
bb: 'BitBucket',
@@ -22,7 +20,7 @@ export function providerToName(provider) {
}[provider.toLowerCase()]
}
-export function providerToInternalProvider(provider) {
+export function providerToInternalProvider(provider: Provider) {
return {
gh: 'github',
bb: 'bitbucket',
@@ -39,34 +37,17 @@ export function providerToInternalProvider(provider) {
}[provider.toLowerCase()]
}
-export function providerImage(providerName) {
- return {
- Github: githubLogo,
- Gitlab: gitlabLogo,
- BitBucket: bitbucketLogo,
- 'Github Enterprise': githubLogo,
- 'Gitlab Enterprise': gitlabLogo,
- 'BitBucket Server': bitbucketLogo,
- }[providerToName(providerName)]
-}
-
-export function providerFeedback(providerName) {
- return {
- Github: 'https://github.com/codecov/Codecov-user-feedback/issues/1',
- Gitlab:
- 'https://gitlab.com/codecov-open-source/codecov-user-feedback/-/issues/1',
- BitBucket:
- 'https://bitbucket.org/kylemann/codecov/issues/1/wed-love-your-feedback',
- 'Github Enterprise':
- 'https://github.com/codecov/Codecov-user-feedback/issues/1',
- 'Gitlab Enterprise':
- 'https://gitlab.com/codecov-open-source/codecov-user-feedback/-/issues/1',
- 'BitBucket Server':
- 'https://bitbucket.org/kylemann/codecov/issues/1/wed-love-your-feedback',
- }[providerToName(providerName)]
-}
-
-export function getProviderCommitURL({ provider, owner, repo, commit }) {
+export function getProviderCommitURL({
+ provider,
+ owner,
+ repo,
+ commit,
+}: {
+ provider: Provider
+ owner: string
+ repo: string
+ commit: string
+}) {
return {
Github: `https://github.com/${owner}/${repo}/commit/${commit}`,
BitBucket: `https://bitbucket.org/${owner}/${repo}/commits/${commit}`,
@@ -74,10 +55,21 @@ export function getProviderCommitURL({ provider, owner, repo, commit }) {
'Github Enterprise': `${config.GHE_URL}/${owner}/${repo}/commit/${commit}`,
'Gitlab Enterprise': `${config.GLE_URL}/${owner}/${repo}/-/commit/${commit}`,
'BitBucket Server': `${config.BBS_URL}/${owner}/${repo}/commits/${commit}`,
+ // @ts-expect-error
}[providerToName(provider)]
}
-export function getProviderPullURL({ provider, owner, repo, pullId }) {
+export function getProviderPullURL({
+ provider,
+ owner,
+ repo,
+ pullId,
+}: {
+ provider: Provider
+ owner: string
+ repo: string
+ pullId: number
+}) {
return {
Github: `https://github.com/${owner}/${repo}/pull/${pullId}`,
BitBucket: `https://bitbucket.org/${owner}/${repo}/pull-requests/${pullId}`,
@@ -85,5 +77,6 @@ export function getProviderPullURL({ provider, owner, repo, pullId }) {
'Github Enterprise': `${config.GHE_URL}/${owner}/${repo}/pull/${pullId}`,
'Gitlab Enterprise': `${config.GLE_URL}/${owner}/${repo}/-/merge_requests/${pullId}`,
'BitBucket Server': `${config.BBS_URL}/${owner}/${repo}/pull-requests/${pullId}`,
+ // @ts-expect-error
}[providerToName(provider)]
}
diff --git a/src/shared/utils/upgradeForm.test.js b/src/shared/utils/upgradeForm.test.js
index 0e359a9f91..f56aec08a7 100644
--- a/src/shared/utils/upgradeForm.test.js
+++ b/src/shared/utils/upgradeForm.test.js
@@ -149,7 +149,7 @@ describe('getDefaultValuesUpgradeForm', () => {
})
expect(data).toStrictEqual({
- newPlan: 'users-teamm',
+ newPlan: Plans.USERS_TEAMM,
seats: 2,
})
})