planFeature.spec.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {BillingConfigFixture} from 'getsentry-test/fixtures/billingConfig';
  3. import {PlanDetailsLookupFixture} from 'getsentry-test/fixtures/planDetailsLookup';
  4. import {SubscriptionFixture} from 'getsentry-test/fixtures/subscription';
  5. import {render, waitFor} from 'sentry-test/reactTestingLibrary';
  6. import PlanFeature from 'getsentry/components/features/planFeature';
  7. import SubscriptionStore from 'getsentry/stores/subscriptionStore';
  8. import {PlanTier} from 'getsentry/types';
  9. describe('PlanFeature', function () {
  10. const organization = OrganizationFixture();
  11. beforeEach(() => {
  12. SubscriptionStore.init();
  13. MockApiClient.addMockResponse({
  14. url: `/customers/${organization.slug}/billing-config/`,
  15. query: {tier: 'am2'},
  16. body: BillingConfigFixture(PlanTier.AM2),
  17. });
  18. });
  19. it('provides the plan required for a feature', async function () {
  20. const mockFn = jest.fn(() => null);
  21. const sub = SubscriptionFixture({organization, planTier: PlanTier.MM2});
  22. SubscriptionStore.set(organization.slug, sub);
  23. render(
  24. <PlanFeature organization={organization} features={['sso-basic']}>
  25. {mockFn}
  26. </PlanFeature>
  27. );
  28. await waitFor(() => {
  29. expect(mockFn).toHaveBeenCalledWith({
  30. plan: PlanDetailsLookupFixture('am2_team'),
  31. tierChange: 'am2',
  32. });
  33. });
  34. });
  35. it('provides the business plan', async function () {
  36. const mockFn = jest.fn(() => null);
  37. const sub = SubscriptionFixture({organization, planTier: PlanTier.MM2});
  38. SubscriptionStore.set(organization.slug, sub);
  39. render(
  40. <PlanFeature organization={organization} features={['discard-groups']}>
  41. {mockFn}
  42. </PlanFeature>
  43. );
  44. await waitFor(() => {
  45. expect(mockFn).toHaveBeenCalledWith({
  46. plan: PlanDetailsLookupFixture('am2_business'),
  47. tierChange: 'am2',
  48. });
  49. });
  50. });
  51. it('provides no plan if the feature is not on a plan', async function () {
  52. const mockFn = jest.fn(() => null);
  53. const sub = SubscriptionFixture({organization, planTier: PlanTier.MM2});
  54. SubscriptionStore.set(organization.slug, sub);
  55. render(
  56. <PlanFeature organization={organization} features={['invalid-feature']}>
  57. {mockFn}
  58. </PlanFeature>
  59. );
  60. await waitFor(() => {
  61. expect(mockFn).toHaveBeenCalledWith({plan: null, tierChange: null});
  62. });
  63. });
  64. it('provides a plan when the tiers mismatch', async function () {
  65. const mockFn = jest.fn(() => null);
  66. const sub = SubscriptionFixture({
  67. organization,
  68. contractInterval: 'annual',
  69. planTier: PlanTier.MM2,
  70. });
  71. SubscriptionStore.set(organization.slug, sub);
  72. render(
  73. <PlanFeature organization={organization} features={['discard-groups']}>
  74. {mockFn}
  75. </PlanFeature>
  76. );
  77. await waitFor(() => {
  78. expect(mockFn).toHaveBeenCalledWith({
  79. plan: PlanDetailsLookupFixture('am2_business'),
  80. tierChange: 'am2',
  81. });
  82. });
  83. });
  84. it('reports tier change as null when no tier change is required', async function () {
  85. const mockFn = jest.fn(() => null);
  86. const sub = SubscriptionFixture({organization, planTier: 'am2'});
  87. SubscriptionStore.set(organization.slug, sub);
  88. render(
  89. <PlanFeature organization={organization} features={['discard-groups']}>
  90. {mockFn}
  91. </PlanFeature>
  92. );
  93. await waitFor(() => {
  94. expect(mockFn).toHaveBeenCalledWith({
  95. plan: PlanDetailsLookupFixture('am2_business'),
  96. tierChange: null,
  97. });
  98. });
  99. });
  100. it('provides the business plan for am3', async function () {
  101. const mockFn = jest.fn(() => null);
  102. MockApiClient.addMockResponse({
  103. url: `/customers/${organization.slug}/billing-config/`,
  104. query: {tier: 'am3'},
  105. body: BillingConfigFixture(PlanTier.AM3),
  106. });
  107. const sub = SubscriptionFixture({organization, plan: 'am3_team'});
  108. SubscriptionStore.set(organization.slug, sub);
  109. render(
  110. <PlanFeature organization={organization} features={['discard-groups']}>
  111. {mockFn}
  112. </PlanFeature>
  113. );
  114. await waitFor(() => {
  115. expect(mockFn).toHaveBeenCalledWith({
  116. plan: PlanDetailsLookupFixture('am3_business'),
  117. tierChange: 'am3',
  118. });
  119. });
  120. });
  121. it('offers business upgrade if on sponsored plan', async function () {
  122. const mockFn = jest.fn(() => null);
  123. const sub = SubscriptionFixture({
  124. organization,
  125. plan: 'am2_sponsored',
  126. isSponsored: true,
  127. });
  128. SubscriptionStore.set(organization.slug, sub);
  129. render(
  130. <PlanFeature organization={organization} features={['monitor-seat-billing']}>
  131. {mockFn}
  132. </PlanFeature>
  133. );
  134. await waitFor(() => {
  135. expect(mockFn).toHaveBeenCalledWith({
  136. plan: PlanDetailsLookupFixture('am2_business'),
  137. tierChange: 'am2',
  138. });
  139. });
  140. });
  141. });