index.spec.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import {InstallWizardFixture} from 'sentry-fixture/installWizard';
  2. import {OrganizationFixture} from 'sentry-fixture/organization';
  3. import {initializeOrg} from 'sentry-test/initializeOrg';
  4. import {render, screen} from 'sentry-test/reactTestingLibrary';
  5. import ConfigStore from 'sentry/stores/configStore';
  6. import HookStore from 'sentry/stores/hookStore';
  7. import App from 'sentry/views/app';
  8. function HookWrapper(props) {
  9. return (
  10. <div data-test-id="hook-wrapper">
  11. {props.children}
  12. <span>{JSON.stringify(props?.organization ?? {}, null, 2)}</span>
  13. </div>
  14. );
  15. }
  16. describe('App', function () {
  17. const configState = ConfigStore.getState();
  18. const {routerProps} = initializeOrg();
  19. beforeEach(function () {
  20. ConfigStore.init();
  21. ConfigStore.loadInitialData(configState);
  22. HookStore.init();
  23. MockApiClient.addMockResponse({
  24. url: '/organizations/',
  25. body: [OrganizationFixture({slug: 'billy-org', name: 'billy org'})],
  26. });
  27. MockApiClient.addMockResponse({
  28. url: '/assistant/',
  29. body: [],
  30. });
  31. MockApiClient.addMockResponse({
  32. url: '/internal/options/?query=is:required',
  33. body: InstallWizardFixture(),
  34. });
  35. });
  36. afterEach(function () {
  37. jest.resetAllMocks();
  38. });
  39. it('renders', function () {
  40. render(
  41. <App {...routerProps}>
  42. <div>placeholder content</div>
  43. </App>
  44. );
  45. expect(screen.getByText('placeholder content')).toBeInTheDocument();
  46. expect(window.location.replace).not.toHaveBeenCalled();
  47. });
  48. it('renders NewsletterConsent', async function () {
  49. const user = ConfigStore.get('user');
  50. user.flags.newsletter_consent_prompt = true;
  51. render(
  52. <App {...routerProps}>
  53. <div>placeholder content</div>
  54. </App>
  55. );
  56. const updatesViaEmail = await screen.findByText(
  57. 'Yes, I would like to receive updates via email',
  58. undefined,
  59. {timeout: 2000, interval: 100}
  60. );
  61. expect(updatesViaEmail).toBeInTheDocument();
  62. user.flags.newsletter_consent_prompt = false;
  63. });
  64. it('renders PartnershipAgreement', function () {
  65. ConfigStore.set('partnershipAgreementPrompt', {
  66. partnerDisplayName: 'Foo',
  67. agreements: ['standard', 'partner_presence'],
  68. });
  69. HookStore.add('component:partnership-agreement', () => <HookWrapper key={0} />);
  70. render(
  71. <App {...routerProps}>
  72. <div>placeholder content</div>
  73. </App>
  74. );
  75. expect(HookStore.get('component:partnership-agreement')).toHaveLength(1);
  76. expect(screen.getByTestId('hook-wrapper')).toBeInTheDocument();
  77. });
  78. it('does not render PartnerAgreement for non-partnered orgs', function () {
  79. ConfigStore.set('partnershipAgreementPrompt', null);
  80. HookStore.add('component:partnership-agreement', () => <HookWrapper key={0} />);
  81. render(
  82. <App {...routerProps}>
  83. <div>placeholder content</div>
  84. </App>
  85. );
  86. expect(screen.getByText('placeholder content')).toBeInTheDocument();
  87. expect(screen.queryByTestId('hook-wrapper')).not.toBeInTheDocument();
  88. });
  89. it('renders InstallWizard for self-hosted', async function () {
  90. ConfigStore.get('user').isSuperuser = true;
  91. ConfigStore.set('needsUpgrade', true);
  92. ConfigStore.set('isSelfHosted', true);
  93. MockApiClient.addMockResponse({
  94. url: '/internal/health/',
  95. body: {
  96. problems: [],
  97. },
  98. });
  99. render(
  100. <App {...routerProps}>
  101. <div>placeholder content</div>
  102. </App>
  103. );
  104. const completeSetup = await screen.findByText(
  105. 'Complete setup by filling out the required configuration.'
  106. );
  107. expect(completeSetup).toBeInTheDocument();
  108. });
  109. it('does not render InstallWizard for non-self-hosted', function () {
  110. ConfigStore.get('user').isSuperuser = true;
  111. ConfigStore.set('needsUpgrade', true);
  112. ConfigStore.set('isSelfHosted', false);
  113. render(
  114. <App {...routerProps}>
  115. <div>placeholder content</div>
  116. </App>
  117. );
  118. expect(screen.getByText('placeholder content')).toBeInTheDocument();
  119. expect(window.location.replace).not.toHaveBeenCalled();
  120. });
  121. it('redirects to sentryUrl on invalid org slug', function () {
  122. const {sentryUrl} = ConfigStore.get('links');
  123. render(
  124. <App {...routerProps} params={{orgId: 'albertos%2fapples'}}>
  125. <div>placeholder content</div>
  126. </App>
  127. );
  128. expect(screen.queryByText('placeholder content')).not.toBeInTheDocument();
  129. expect(sentryUrl).toEqual('https://sentry.io');
  130. expect(window.location.replace).toHaveBeenCalledWith('https://sentry.io');
  131. expect(window.location.replace).toHaveBeenCalledTimes(1);
  132. });
  133. it('adds health issues to alertstore', async function () {
  134. const getMock = MockApiClient.addMockResponse({
  135. url: '/internal/health/',
  136. body: {
  137. healthy: false,
  138. problems: [
  139. {
  140. id: 'abc123',
  141. message: 'Celery workers have not checked in',
  142. severity: 'critical',
  143. },
  144. ],
  145. },
  146. });
  147. const restore = ConfigStore.get('isSelfHosted');
  148. ConfigStore.set('isSelfHosted', true);
  149. render(
  150. <App {...routerProps}>
  151. <div>placeholder content</div>
  152. </App>
  153. );
  154. ConfigStore.config.isSelfHosted = restore;
  155. expect(getMock).toHaveBeenCalled();
  156. expect(
  157. await screen.findByText(/Celery workers have not checked in/)
  158. ).toBeInTheDocument();
  159. });
  160. });