productSelection.spec.tsx 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {initializeOrg} from 'sentry-test/initializeOrg';
  3. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  4. import {textWithMarkupMatcher} from 'sentry-test/utils';
  5. import {
  6. platformProductAvailability,
  7. ProductSelection,
  8. ProductSolution,
  9. } from 'sentry/components/onboarding/productSelection';
  10. describe('Onboarding Product Selection', function () {
  11. const organization = OrganizationFixture({
  12. features: ['session-replay', 'performance-view', 'profiling-view'],
  13. });
  14. it('renders default state', async function () {
  15. const {router, routerContext} = initializeOrg({
  16. router: {
  17. location: {
  18. query: {
  19. product: [
  20. ProductSolution.PERFORMANCE_MONITORING,
  21. ProductSolution.SESSION_REPLAY,
  22. ],
  23. },
  24. },
  25. params: {},
  26. },
  27. });
  28. render(<ProductSelection organization={organization} platform="javascript-react" />, {
  29. context: routerContext,
  30. });
  31. // Introduction
  32. expect(
  33. screen.getByText(
  34. textWithMarkupMatcher(/In this quick guide you’ll use npm or yarn/)
  35. )
  36. ).toBeInTheDocument();
  37. expect(screen.queryByText('Prefer to set up Sentry using')).not.toBeInTheDocument();
  38. // Error monitoring shall be checked and disabled by default
  39. expect(screen.getByRole('checkbox', {name: 'Error Monitoring'})).toBeChecked();
  40. // Tooltip with explanation shall be displayed on hover
  41. await userEvent.hover(screen.getByRole('checkbox', {name: 'Error Monitoring'}));
  42. expect(
  43. await screen.findByText(/Let's admit it, we all have errors/)
  44. ).toBeInTheDocument();
  45. // Try to uncheck error monitoring
  46. await userEvent.click(screen.getByRole('checkbox', {name: 'Error Monitoring'}));
  47. await waitFor(() => expect(router.push).not.toHaveBeenCalled());
  48. // Performance monitoring shall be checked and enabled by default
  49. expect(screen.getByRole('checkbox', {name: 'Performance Monitoring'})).toBeChecked();
  50. expect(screen.getByRole('checkbox', {name: 'Performance Monitoring'})).toBeEnabled();
  51. // Tooltip with explanation shall be displayed on hover
  52. await userEvent.hover(screen.getByRole('checkbox', {name: 'Performance Monitoring'}));
  53. expect(
  54. await screen.findByText(/Automatic performance issue detection/)
  55. ).toBeInTheDocument();
  56. // Uncheck performance monitoring
  57. await userEvent.click(screen.getByRole('checkbox', {name: 'Performance Monitoring'}));
  58. await waitFor(() =>
  59. expect(router.replace).toHaveBeenCalledWith({
  60. pathname: undefined,
  61. query: {product: [ProductSolution.SESSION_REPLAY]},
  62. })
  63. );
  64. // Session replay shall be checked and enabled by default
  65. expect(screen.getByRole('checkbox', {name: 'Session Replay'})).toBeChecked();
  66. expect(screen.getByRole('checkbox', {name: 'Session Replay'})).toBeEnabled();
  67. // Uncheck sesseion replay
  68. await userEvent.click(screen.getByRole('checkbox', {name: 'Session Replay'}));
  69. await waitFor(() =>
  70. expect(router.replace).toHaveBeenCalledWith({
  71. pathname: undefined,
  72. query: {product: [ProductSolution.PERFORMANCE_MONITORING]},
  73. })
  74. );
  75. // Tooltip with explanation shall be displayed on hover
  76. await userEvent.hover(screen.getByRole('checkbox', {name: 'Session Replay'}));
  77. expect(
  78. await screen.findByText(/Video-like reproductions of user sessions/)
  79. ).toBeInTheDocument();
  80. });
  81. it('renders for Loader Script', async function () {
  82. const {routerContext} = initializeOrg({
  83. router: {
  84. location: {
  85. query: {
  86. product: [
  87. ProductSolution.PERFORMANCE_MONITORING,
  88. ProductSolution.SESSION_REPLAY,
  89. ],
  90. },
  91. },
  92. params: {},
  93. },
  94. });
  95. const skipLazyLoader = jest.fn();
  96. render(
  97. <ProductSelection
  98. organization={organization}
  99. lazyLoader
  100. skipLazyLoader={skipLazyLoader}
  101. platform="javascript-react"
  102. />,
  103. {
  104. context: routerContext,
  105. }
  106. );
  107. // Introduction
  108. expect(
  109. screen.getByText(
  110. textWithMarkupMatcher(/In this quick guide you’ll use our Loader Script/)
  111. )
  112. ).toBeInTheDocument();
  113. expect(
  114. screen.getByText(
  115. textWithMarkupMatcher(/Prefer to set up Sentry using npm or yarn\?/)
  116. )
  117. ).toBeInTheDocument();
  118. await userEvent.click(screen.getByText('Go here'));
  119. expect(skipLazyLoader).toHaveBeenCalledTimes(1);
  120. });
  121. it('renders disabled product', async function () {
  122. const {router, routerContext} = initializeOrg({
  123. router: {
  124. location: {
  125. query: {product: [ProductSolution.SESSION_REPLAY]},
  126. },
  127. params: {},
  128. },
  129. });
  130. const disabledProducts = {
  131. [ProductSolution.PERFORMANCE_MONITORING]: {
  132. reason: 'Product unavailable in this SDK version',
  133. },
  134. };
  135. render(
  136. <ProductSelection
  137. organization={organization}
  138. disabledProducts={disabledProducts}
  139. platform="javascript-react"
  140. />,
  141. {
  142. context: routerContext,
  143. }
  144. );
  145. // Performance Monitoring shall be unchecked and disabled by default
  146. expect(screen.getByRole('checkbox', {name: 'Performance Monitoring'})).toBeDisabled();
  147. expect(
  148. screen.getByRole('checkbox', {name: 'Performance Monitoring'})
  149. ).not.toBeChecked();
  150. await userEvent.hover(screen.getByRole('checkbox', {name: 'Performance Monitoring'}));
  151. // A tooltip with explanation why the option is disabled shall be displayed on hover
  152. expect(
  153. await screen.findByText(
  154. disabledProducts[ProductSolution.PERFORMANCE_MONITORING].reason
  155. )
  156. ).toBeInTheDocument();
  157. await userEvent.click(screen.getByRole('checkbox', {name: 'Performance Monitoring'}));
  158. // Try to uncheck performance monitoring
  159. await waitFor(() => expect(router.push).not.toHaveBeenCalled());
  160. });
  161. it('does not render Session Replay', async function () {
  162. platformProductAvailability['javascript-react'] = [
  163. ProductSolution.PERFORMANCE_MONITORING,
  164. ];
  165. const {router, routerContext} = initializeOrg({
  166. router: {
  167. location: {
  168. query: {product: [ProductSolution.SESSION_REPLAY]},
  169. },
  170. params: {},
  171. },
  172. });
  173. render(<ProductSelection organization={organization} platform="javascript-react" />, {
  174. context: routerContext,
  175. });
  176. expect(
  177. screen.queryByRole('checkbox', {name: 'Session Replay'})
  178. ).not.toBeInTheDocument();
  179. // router.replace is called to remove session-replay from query
  180. await waitFor(() =>
  181. expect(router.replace).toHaveBeenCalledWith({
  182. pathname: undefined,
  183. query: {product: [ProductSolution.PERFORMANCE_MONITORING]},
  184. })
  185. );
  186. });
  187. it('render Profiling', async function () {
  188. const {router, routerContext} = initializeOrg({
  189. router: {
  190. location: {
  191. query: {product: [ProductSolution.PERFORMANCE_MONITORING]},
  192. },
  193. params: {},
  194. },
  195. });
  196. render(<ProductSelection organization={organization} platform="python-django" />, {
  197. context: routerContext,
  198. });
  199. expect(screen.getByRole('checkbox', {name: 'Profiling'})).toBeInTheDocument();
  200. // router.replace is called to add profiling from query
  201. await waitFor(() =>
  202. expect(router.replace).toHaveBeenCalledWith({
  203. pathname: undefined,
  204. query: {
  205. product: [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING],
  206. },
  207. })
  208. );
  209. });
  210. it('renders npm & yarn info text', function () {
  211. const {routerContext} = initializeOrg({
  212. router: {
  213. location: {
  214. query: {product: [ProductSolution.PERFORMANCE_MONITORING]},
  215. },
  216. params: {},
  217. },
  218. });
  219. render(<ProductSelection organization={organization} platform="javascript-react" />, {
  220. context: routerContext,
  221. });
  222. expect(screen.queryByText('npm')).toBeInTheDocument();
  223. expect(screen.queryByText('yarn')).toBeInTheDocument();
  224. });
  225. it('does not render npm & yarn info text', function () {
  226. const {routerContext} = initializeOrg({
  227. router: {
  228. location: {
  229. query: {product: [ProductSolution.PERFORMANCE_MONITORING]},
  230. },
  231. params: {},
  232. },
  233. });
  234. render(<ProductSelection organization={organization} platform="python-django" />, {
  235. context: routerContext,
  236. });
  237. expect(screen.queryByText('npm')).not.toBeInTheDocument();
  238. expect(screen.queryByText('yarn')).not.toBeInTheDocument();
  239. });
  240. });