productSelection.spec.tsx 8.4 KB

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