sidebarNavigationItem.spec.tsx 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {BillingConfigFixture} from 'getsentry-test/fixtures/billingConfig';
  3. import {SubscriptionFixture} from 'getsentry-test/fixtures/subscription';
  4. import {render, screen, waitFor} from 'sentry-test/reactTestingLibrary';
  5. import {SidebarNavigationItem} from 'getsentry/components/sidebarNavigationItem';
  6. import SubscriptionStore from 'getsentry/stores/subscriptionStore';
  7. import {PlanTier} from 'getsentry/types';
  8. describe('SidebarNavigationItem', function () {
  9. let billingConfigMock: any;
  10. const renderFunc = jest.fn().mockImplementation(function simpleRenderFunction({
  11. additionalContent,
  12. Wrapper,
  13. disabled,
  14. }) {
  15. return (
  16. <Wrapper>
  17. <a data-test-id="link" aria-disabled={disabled}>
  18. <span>Some Content</span>
  19. <span>{additionalContent}</span>
  20. </a>
  21. </Wrapper>
  22. );
  23. });
  24. beforeEach(function () {
  25. const organization = OrganizationFixture();
  26. billingConfigMock = MockApiClient.addMockResponse({
  27. url: `/customers/${organization.slug}/billing-config/`,
  28. method: 'GET',
  29. body: BillingConfigFixture(PlanTier.AM3),
  30. });
  31. });
  32. const verifyItemIsEnabled = () => {
  33. expect(screen.getByTestId('link')).toHaveAttribute('aria-disabled', 'false');
  34. expect(screen.getByTestId('link')).not.toHaveAttribute('aria-describedby');
  35. expect(screen.queryByTestId('power-icon')).not.toBeInTheDocument();
  36. };
  37. const verifyItemIsDisabled = () => {
  38. expect(screen.getByTestId('link')).toHaveAttribute('aria-disabled', 'true');
  39. expect(screen.getByTestId('link')).toHaveAttribute('aria-describedby');
  40. expect(screen.getByTestId('power-icon')).toBeInTheDocument();
  41. };
  42. it('allows items that do not have blocking conditions', function () {
  43. const organization = OrganizationFixture();
  44. const subscription = SubscriptionFixture({organization});
  45. subscription.planDetails.features = [];
  46. const id = 'metrics';
  47. SubscriptionStore.set(organization.slug, subscription);
  48. render(
  49. <SidebarNavigationItem
  50. id={id}
  51. organization={organization}
  52. subscription={subscription}
  53. >
  54. {renderFunc}
  55. </SidebarNavigationItem>
  56. );
  57. verifyItemIsEnabled();
  58. });
  59. it('provides eligible items with non-blocking render props', function () {
  60. const organization = OrganizationFixture();
  61. const subscription = SubscriptionFixture({
  62. organization,
  63. plan: 'am2_business',
  64. isFree: true,
  65. });
  66. subscription.planDetails.features = ['insights-addon-modules'];
  67. const id = 'llm-monitoring';
  68. SubscriptionStore.set(organization.slug, subscription);
  69. render(
  70. <SidebarNavigationItem
  71. id={id}
  72. organization={organization}
  73. subscription={subscription}
  74. >
  75. {renderFunc}
  76. </SidebarNavigationItem>
  77. );
  78. verifyItemIsEnabled();
  79. });
  80. it('provides ineligible items with blocking render props', function () {
  81. const organization = OrganizationFixture({
  82. features: ['insights-initial-modules'],
  83. });
  84. const subscription = SubscriptionFixture({
  85. organization,
  86. plan: 'am2_f',
  87. isFree: true,
  88. });
  89. subscription.planDetails.features = [];
  90. const id = 'llm-monitoring';
  91. SubscriptionStore.set(organization.slug, subscription);
  92. render(
  93. <SidebarNavigationItem
  94. id={id}
  95. organization={organization}
  96. subscription={subscription}
  97. >
  98. {renderFunc}
  99. </SidebarNavigationItem>
  100. );
  101. verifyItemIsDisabled();
  102. });
  103. it('considers features of the plan trial', async function () {
  104. // The `"am3_team"` plan does not have the `insights-addon-modules` feature. The `"am3_business"` plan _does_ have the feature. The "LLM Monitoring" sidebar item should be enabled
  105. const organization = OrganizationFixture();
  106. const subscription = SubscriptionFixture({
  107. organization,
  108. plan: 'am3_team',
  109. trialPlan: 'am3_business',
  110. });
  111. const id = 'llm-monitoring';
  112. SubscriptionStore.set(organization.slug, subscription);
  113. render(
  114. <SidebarNavigationItem
  115. id={id}
  116. organization={organization}
  117. subscription={subscription}
  118. >
  119. {renderFunc}
  120. </SidebarNavigationItem>
  121. );
  122. await waitFor(() => {
  123. expect(billingConfigMock).toHaveBeenCalled();
  124. });
  125. verifyItemIsEnabled();
  126. });
  127. it('considers features of the organization', async function () {
  128. // The `"am3_team"` plan does not have the `insights-addon-modules` feature. The organization _does_ have the feature. This can happen if the flag is manually turned on via an allowlist. "LLM Monitoring" should be enabled
  129. const organization = OrganizationFixture({
  130. features: ['insights-addon-modules'],
  131. });
  132. const subscription = SubscriptionFixture({
  133. organization,
  134. plan: 'am3_team',
  135. });
  136. const id = 'llm-monitoring';
  137. SubscriptionStore.set(organization.slug, subscription);
  138. render(
  139. <SidebarNavigationItem
  140. id={id}
  141. organization={organization}
  142. subscription={subscription}
  143. >
  144. {renderFunc}
  145. </SidebarNavigationItem>
  146. );
  147. await waitFor(() => {
  148. expect(billingConfigMock).toHaveBeenCalled();
  149. });
  150. verifyItemIsEnabled();
  151. });
  152. it('covers "Insights" link with an upsell if no Insights are available', async function () {
  153. const organization = OrganizationFixture();
  154. const subscription = SubscriptionFixture({
  155. organization,
  156. plan: 'am3_team',
  157. });
  158. const id = 'sidebar-accordion-insights-item';
  159. SubscriptionStore.set(organization.slug, subscription);
  160. render(
  161. <SidebarNavigationItem
  162. id={id}
  163. organization={organization}
  164. subscription={subscription}
  165. >
  166. {renderFunc}
  167. </SidebarNavigationItem>
  168. );
  169. await waitFor(() => {
  170. expect(billingConfigMock).toHaveBeenCalled();
  171. });
  172. expect(screen.getByTestId('link')).toHaveAttribute('aria-disabled', 'true');
  173. expect(screen.getByTestId('link')).toHaveAttribute('aria-describedby');
  174. expect(screen.getByTestId('power-icon')).toBeInTheDocument();
  175. });
  176. it('omits Turbo icon from Insights links if none are available', async function () {
  177. const organization = OrganizationFixture();
  178. const subscription = SubscriptionFixture({
  179. organization,
  180. plan: 'am3_team',
  181. });
  182. const id = 'performance-database';
  183. SubscriptionStore.set(organization.slug, subscription);
  184. render(
  185. <SidebarNavigationItem
  186. id={id}
  187. organization={organization}
  188. subscription={subscription}
  189. >
  190. {renderFunc}
  191. </SidebarNavigationItem>
  192. );
  193. await waitFor(() => {
  194. expect(billingConfigMock).toHaveBeenCalled();
  195. });
  196. expect(screen.getByTestId('link')).toHaveAttribute('aria-disabled', 'true');
  197. expect(screen.getByTestId('link')).toHaveAttribute('aria-describedby');
  198. expect(screen.queryByTestId('power-icon')).not.toBeInTheDocument();
  199. });
  200. });