PlanUpdateSidePanel.test.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import { screen } from '@testing-library/react'
  2. import { beforeEach, describe, expect, it, vi } from 'vitest'
  3. import { PlanUpdateSidePanel } from './PlanUpdateSidePanel'
  4. import { MANAGED_BY } from '@/lib/constants/infrastructure'
  5. import { createMockOrganization, render } from '@/tests/helpers'
  6. const mockSelectedOrganization = vi.hoisted(() => vi.fn())
  7. const mockPush = vi.hoisted(() => vi.fn())
  8. const mockPartnerManagedResource = vi.hoisted(() => vi.fn())
  9. vi.mock('common', async (importOriginal) => {
  10. const original = (await importOriginal()) as typeof import('common')
  11. return {
  12. ...original,
  13. useParams: () => ({ slug: 'stripe-org' }),
  14. }
  15. })
  16. vi.mock('next/router', () => ({
  17. useRouter: () => ({
  18. pathname: '/org/[slug]/billing',
  19. query: {},
  20. push: mockPush,
  21. }),
  22. }))
  23. vi.mock('shared-data/plans', () => ({
  24. plans: [
  25. { id: 'tier_free', planId: 'free', name: 'Free', costUnit: '/ month', features: [] },
  26. { id: 'tier_pro', planId: 'pro', name: 'Pro', costUnit: '/ month', features: [] },
  27. ],
  28. }))
  29. vi.mock('@/hooks/misc/useSelectedOrganization', () => ({
  30. useSelectedOrganizationQuery: () => ({ data: mockSelectedOrganization() }),
  31. }))
  32. vi.mock('@/data/telemetry/send-event-mutation', () => ({
  33. useSendEventMutation: () => ({ mutate: vi.fn() }),
  34. }))
  35. vi.mock('@/hooks/misc/useCheckPermissions', () => ({
  36. useAsyncCheckPermissions: () => ({ can: true }),
  37. }))
  38. vi.mock('@/state/organization-settings', () => ({
  39. useOrgSettingsPageStateSnapshot: () => ({
  40. panelKey: 'subscriptionPlan',
  41. setPanelKey: vi.fn(),
  42. }),
  43. }))
  44. vi.mock('@/data/projects/org-projects-infinite-query', () => ({
  45. useOrgProjectsInfiniteQuery: () => ({ data: undefined }),
  46. }))
  47. vi.mock('@/data/organizations/free-project-limit-check-query', () => ({
  48. useFreeProjectLimitCheckQuery: () => ({ data: [] }),
  49. }))
  50. vi.mock('@/data/organizations/organization-query', () => ({
  51. useOrganizationQuery: () => ({ data: { has_oriole_project: false } }),
  52. }))
  53. vi.mock('@/data/subscriptions/org-subscription-query', () => ({
  54. useOrgSubscriptionQuery: () => ({
  55. data: { plan: { id: 'free', name: 'Free' } },
  56. isSuccess: true,
  57. }),
  58. }))
  59. vi.mock('@/data/subscriptions/org-plans-query', () => ({
  60. useOrgPlansQuery: () => ({
  61. data: {
  62. plans: [
  63. { id: 'free', price: 0 },
  64. { id: 'pro', price: 25 },
  65. ],
  66. },
  67. isPending: false,
  68. }),
  69. }))
  70. vi.mock('@/data/organizations/organization-billing-subscription-preview', () => ({
  71. useOrganizationBillingSubscriptionPreview: () => ({}),
  72. }))
  73. vi.mock('@/components/ui/PartnerManagedResource', () => ({
  74. default: (props: any) => {
  75. mockPartnerManagedResource(props)
  76. return <div data-testid="partner-managed-resource">{props.details}</div>
  77. },
  78. }))
  79. vi.mock('./EnterpriseCard', () => ({
  80. EnterpriseCard: () => <div>Enterprise</div>,
  81. }))
  82. vi.mock('./DowngradeModal', () => ({
  83. default: () => null,
  84. }))
  85. vi.mock('./ExitSurveyModal', () => ({
  86. ExitSurveyModal: () => null,
  87. }))
  88. vi.mock('./UpgradeModal', () => ({
  89. default: () => null,
  90. }))
  91. vi.mock('./MembersExceedLimitModal', () => ({
  92. default: () => null,
  93. }))
  94. vi.mock('./SubscriptionPlanUpdateDialog', () => ({
  95. SubscriptionPlanUpdateDialog: () => null,
  96. }))
  97. describe('PlanUpdateSidePanel', () => {
  98. beforeEach(() => {
  99. vi.clearAllMocks()
  100. mockSelectedOrganization.mockReturnValue(
  101. createMockOrganization({
  102. slug: 'stripe-org',
  103. billing_partner: null,
  104. integration_source: 'stripe_projects',
  105. managed_by: MANAGED_BY.STRIPE_PROJECTS,
  106. })
  107. )
  108. })
  109. it('shows Stripe-managed messaging without treating Stripe orgs as partner-billed', () => {
  110. render(<PlanUpdateSidePanel />)
  111. expect(screen.getByTestId('partner-managed-resource')).toBeInTheDocument()
  112. expect(screen.getByText('stripe projects upgrade briven/free')).toBeInTheDocument()
  113. expect(screen.getByRole('button', { name: 'Upgrade to Pro' })).toBeInTheDocument()
  114. })
  115. it('uses the current plan in the Stripe Projects upgrade command', () => {
  116. mockSelectedOrganization.mockReturnValue(
  117. createMockOrganization({
  118. slug: 'stripe-org',
  119. billing_partner: null,
  120. integration_source: 'stripe_projects',
  121. managed_by: MANAGED_BY.STRIPE_PROJECTS,
  122. plan: { id: 'pro', name: 'Pro' },
  123. })
  124. )
  125. render(<PlanUpdateSidePanel />)
  126. expect(screen.getByText('stripe projects upgrade briven/pro')).toBeInTheDocument()
  127. })
  128. it('uses the Stripe Projects downgrade command for team plans', () => {
  129. mockSelectedOrganization.mockReturnValue(
  130. createMockOrganization({
  131. slug: 'stripe-org',
  132. billing_partner: null,
  133. integration_source: 'stripe_projects',
  134. managed_by: MANAGED_BY.STRIPE_PROJECTS,
  135. plan: { id: 'team', name: 'Team' },
  136. })
  137. )
  138. render(<PlanUpdateSidePanel />)
  139. expect(screen.getByText('stripe projects downgrade briven/team')).toBeInTheDocument()
  140. })
  141. it('still shows partner-managed messaging for billing-partner orgs', () => {
  142. mockSelectedOrganization.mockReturnValue(
  143. createMockOrganization({
  144. slug: 'aws-org',
  145. billing_partner: 'aws_marketplace',
  146. managed_by: MANAGED_BY.AWS_MARKETPLACE,
  147. })
  148. )
  149. render(<PlanUpdateSidePanel />)
  150. expect(screen.getByTestId('partner-managed-resource')).toBeInTheDocument()
  151. })
  152. })