genAiAccess.spec.tsx 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {SubscriptionFixture} from 'getsentry-test/fixtures/subscription';
  3. import {renderHook} from 'sentry-test/reactTestingLibrary';
  4. import {BillingType} from 'getsentry/types';
  5. import {useGenAiConsentButtonAccess} from './genAiAccess';
  6. // Mock the hooks that useGenAiConsentButtonAccess depends on
  7. jest.mock('sentry/utils/useOrganization');
  8. jest.mock('sentry/utils/useUser');
  9. jest.mock('sentry/utils/regions', () => ({
  10. getRegionDataFromOrganization: jest.fn(),
  11. }));
  12. const mockUseOrganization = jest.requireMock('sentry/utils/useOrganization').default;
  13. const mockUseUser = jest.requireMock('sentry/utils/useUser').useUser;
  14. const mockGetRegionData =
  15. jest.requireMock('sentry/utils/regions').getRegionDataFromOrganization;
  16. describe('useGenAiConsentButtonAccess', function () {
  17. // Reset all mocks before each test
  18. beforeEach(() => {
  19. mockUseUser.mockReset();
  20. mockUseOrganization.mockReset();
  21. mockGetRegionData.mockReset();
  22. });
  23. describe('Region-based access', function () {
  24. it('disables access for non-US regions', function () {
  25. const organization = OrganizationFixture();
  26. const subscription = SubscriptionFixture({organization});
  27. mockUseOrganization.mockReturnValue(organization);
  28. mockGetRegionData.mockReturnValue({name: 'de'});
  29. mockUseUser.mockReturnValue({isSuperuser: false});
  30. const {result} = renderHook(() => useGenAiConsentButtonAccess({subscription}));
  31. expect(result.current).toEqual(
  32. expect.objectContaining({
  33. isDisabled: true,
  34. message: 'This feature is not available in your region.',
  35. isUsRegion: false,
  36. })
  37. );
  38. });
  39. it('enables access for US region with proper permissions', function () {
  40. const organization = OrganizationFixture({
  41. access: ['org:billing'],
  42. });
  43. const subscription = SubscriptionFixture({
  44. organization,
  45. type: BillingType.CREDIT_CARD,
  46. });
  47. mockUseOrganization.mockReturnValue(organization);
  48. mockGetRegionData.mockReturnValue({name: 'us'});
  49. mockUseUser.mockReturnValue({isSuperuser: false});
  50. const {result} = renderHook(() => useGenAiConsentButtonAccess({subscription}));
  51. expect(result.current).toEqual(
  52. expect.objectContaining({
  53. isDisabled: false,
  54. message: null,
  55. isUsRegion: true,
  56. })
  57. );
  58. });
  59. });
  60. describe('Touch Customer MSA Updates', function () {
  61. it('disables access for touch customers without MSA update', function () {
  62. const organization = OrganizationFixture({
  63. access: ['org:billing'],
  64. });
  65. const subscription = SubscriptionFixture({
  66. organization,
  67. type: BillingType.INVOICED,
  68. msaUpdatedForDataConsent: false,
  69. });
  70. mockUseOrganization.mockReturnValue(organization);
  71. mockGetRegionData.mockReturnValue({name: 'us'});
  72. mockUseUser.mockReturnValue({isSuperuser: false});
  73. const {result} = renderHook(() => useGenAiConsentButtonAccess({subscription}));
  74. expect(result.current).toEqual(
  75. expect.objectContaining({
  76. isDisabled: true,
  77. message:
  78. 'These changes require updates to your account. Please contact your customer success manager to learn more.',
  79. isTouchCustomerAndNeedsMsaUpdate: true,
  80. })
  81. );
  82. });
  83. it('enables access for touch customers with MSA update', function () {
  84. const organization = OrganizationFixture({
  85. access: ['org:billing'],
  86. });
  87. const subscription = SubscriptionFixture({
  88. organization,
  89. type: BillingType.INVOICED,
  90. msaUpdatedForDataConsent: true,
  91. });
  92. mockUseOrganization.mockReturnValue(organization);
  93. mockGetRegionData.mockReturnValue({name: 'us'});
  94. mockUseUser.mockReturnValue({isSuperuser: false});
  95. const {result} = renderHook(() => useGenAiConsentButtonAccess({subscription}));
  96. expect(result.current).toEqual(
  97. expect.objectContaining({
  98. isDisabled: false,
  99. message: null,
  100. isTouchCustomerAndNeedsMsaUpdate: false,
  101. })
  102. );
  103. });
  104. });
  105. describe('Billing Access', function () {
  106. it('disables access for users without billing access', function () {
  107. const organization = OrganizationFixture({
  108. access: [],
  109. });
  110. const subscription = SubscriptionFixture({
  111. organization,
  112. type: BillingType.CREDIT_CARD,
  113. });
  114. mockUseOrganization.mockReturnValue(organization);
  115. mockGetRegionData.mockReturnValue({name: 'us'});
  116. mockUseUser.mockReturnValue({isSuperuser: false});
  117. const {result} = renderHook(() => useGenAiConsentButtonAccess({subscription}));
  118. expect(result.current).toEqual(
  119. expect.objectContaining({
  120. isDisabled: true,
  121. message:
  122. "You don't have access to manage these billing and subscription details.",
  123. hasBillingAccess: false,
  124. })
  125. );
  126. });
  127. it('enables access for superusers regardless of billing access', function () {
  128. const organization = OrganizationFixture({
  129. access: [],
  130. });
  131. const subscription = SubscriptionFixture({
  132. organization,
  133. type: BillingType.CREDIT_CARD,
  134. });
  135. mockUseOrganization.mockReturnValue(organization);
  136. mockGetRegionData.mockReturnValue({name: 'us'});
  137. mockUseUser.mockReturnValue({isSuperuser: true});
  138. const {result} = renderHook(() => useGenAiConsentButtonAccess({subscription}));
  139. expect(result.current).toEqual(
  140. expect.objectContaining({
  141. isDisabled: false,
  142. message: null,
  143. hasBillingAccess: false,
  144. isSuperuser: true,
  145. })
  146. );
  147. });
  148. it('enables access for users with billing access', function () {
  149. const organization = OrganizationFixture({
  150. access: ['org:billing'],
  151. });
  152. const subscription = SubscriptionFixture({
  153. organization,
  154. type: BillingType.CREDIT_CARD,
  155. });
  156. mockUseOrganization.mockReturnValue(organization);
  157. mockGetRegionData.mockReturnValue({name: 'us'});
  158. mockUseUser.mockReturnValue({isSuperuser: false});
  159. const {result} = renderHook(() => useGenAiConsentButtonAccess({subscription}));
  160. expect(result.current).toEqual(
  161. expect.objectContaining({
  162. isDisabled: false,
  163. message: null,
  164. hasBillingAccess: true,
  165. isSuperuser: false,
  166. })
  167. );
  168. });
  169. });
  170. describe('Combined Conditions', function () {
  171. it('prioritizes region restriction over MSA update requirement', function () {
  172. const organization = OrganizationFixture({
  173. access: ['org:billing'],
  174. });
  175. const subscription = SubscriptionFixture({
  176. organization,
  177. type: BillingType.INVOICED,
  178. msaUpdatedForDataConsent: false,
  179. });
  180. mockUseOrganization.mockReturnValue(organization);
  181. mockGetRegionData.mockReturnValue({name: 'eu'});
  182. mockUseUser.mockReturnValue({isSuperuser: false});
  183. const {result} = renderHook(() => useGenAiConsentButtonAccess({subscription}));
  184. expect(result.current).toEqual(
  185. expect.objectContaining({
  186. isDisabled: true,
  187. message: 'This feature is not available in your region.',
  188. isUsRegion: false,
  189. isTouchCustomerAndNeedsMsaUpdate: true,
  190. })
  191. );
  192. });
  193. it('handles undefined msaUpdatedForDataConsent', function () {
  194. const organization = OrganizationFixture({
  195. access: ['org:billing'],
  196. });
  197. const subscription = SubscriptionFixture({
  198. organization,
  199. type: BillingType.INVOICED,
  200. msaUpdatedForDataConsent: undefined,
  201. });
  202. mockUseOrganization.mockReturnValue(organization);
  203. mockGetRegionData.mockReturnValue({name: 'us'});
  204. mockUseUser.mockReturnValue({isSuperuser: false});
  205. const {result} = renderHook(() => useGenAiConsentButtonAccess({subscription}));
  206. expect(result.current).toEqual(
  207. expect.objectContaining({
  208. isDisabled: true,
  209. message:
  210. 'These changes require updates to your account. Please contact your customer success manager to learn more.',
  211. isTouchCustomerAndNeedsMsaUpdate: true,
  212. })
  213. );
  214. });
  215. });
  216. });