inviteBanner.spec.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import moment from 'moment';
  2. import {render, screen} from 'sentry-test/reactTestingLibrary';
  3. import {setIntersectionObserver} from 'sentry/components/carousel.spec';
  4. import {DEFAULT_SNOOZE_PROMPT_DAYS} from 'sentry/utils/promptIsDismissed';
  5. import {InviteBanner} from 'sentry/views/settings/organizationMembers/inviteBanner';
  6. const missingMembers = {
  7. integration: 'github',
  8. users: TestStubs.MissingMembers(),
  9. };
  10. const noMissingMembers = {
  11. integration: 'github',
  12. users: [],
  13. };
  14. describe('inviteBanner', function () {
  15. beforeEach(function () {
  16. MockApiClient.clearMockResponses();
  17. MockApiClient.addMockResponse({
  18. url: '/organizations/org-slug/missing-members/',
  19. method: 'GET',
  20. body: [],
  21. });
  22. MockApiClient.addMockResponse({
  23. url: '/prompts-activity/',
  24. method: 'GET',
  25. body: {
  26. dismissed_ts: undefined,
  27. snoozed_ts: undefined,
  28. },
  29. });
  30. setIntersectionObserver([
  31. {target: {id: 'left-anchor'}, isIntersecting: true},
  32. {target: {id: 'right-anchor'}, isIntersecting: true},
  33. ]);
  34. });
  35. it('render banners with feature flag', async function () {
  36. const org = TestStubs.Organization({
  37. features: ['integrations-gh-invite'],
  38. });
  39. render(
  40. <InviteBanner
  41. missingMembers={missingMembers}
  42. onSendInvite={() => undefined}
  43. organization={org}
  44. />
  45. );
  46. expect(
  47. await screen.findByRole('heading', {
  48. name: 'Bring your full GitHub team on board in Sentry',
  49. })
  50. ).toBeInTheDocument();
  51. expect(screen.queryAllByTestId('invite-missing-member')).toHaveLength(5);
  52. expect(screen.getByText('See all 5 missing members')).toBeInTheDocument();
  53. });
  54. it('does not render banner if no feature flag', function () {
  55. const org = TestStubs.Organization({
  56. features: [],
  57. });
  58. render(
  59. <InviteBanner
  60. missingMembers={missingMembers}
  61. onSendInvite={() => undefined}
  62. organization={org}
  63. />
  64. );
  65. expect(
  66. screen.queryByRole('heading', {
  67. name: 'Bring your full GitHub team on board in Sentry',
  68. })
  69. ).not.toBeInTheDocument();
  70. });
  71. it('does not render banner if no missing members', function () {
  72. const org = TestStubs.Organization({
  73. features: ['integrations-gh-invite'],
  74. });
  75. render(
  76. <InviteBanner
  77. missingMembers={noMissingMembers}
  78. onSendInvite={() => undefined}
  79. organization={org}
  80. />
  81. );
  82. expect(
  83. screen.queryByRole('heading', {
  84. name: 'Bring your full GitHub team on board in Sentry',
  85. })
  86. ).not.toBeInTheDocument();
  87. });
  88. it('does not render banner if lacking org:write', function () {
  89. const org = TestStubs.Organization({
  90. features: ['integrations-gh-invite'],
  91. access: [],
  92. });
  93. render(
  94. <InviteBanner
  95. missingMembers={noMissingMembers}
  96. onSendInvite={() => undefined}
  97. organization={org}
  98. />
  99. );
  100. expect(
  101. screen.queryByRole('heading', {
  102. name: 'Bring your full GitHub team on board in Sentry',
  103. })
  104. ).not.toBeInTheDocument();
  105. });
  106. it('renders banner if snoozed_ts days is longer than threshold', async function () {
  107. const org = TestStubs.Organization({
  108. features: ['integrations-gh-invite'],
  109. });
  110. const promptResponse = {
  111. dismissed_ts: undefined,
  112. snoozed_ts: moment
  113. .utc()
  114. .subtract(DEFAULT_SNOOZE_PROMPT_DAYS + 1, 'days')
  115. .unix(),
  116. };
  117. MockApiClient.addMockResponse({
  118. url: '/prompts-activity/',
  119. method: 'GET',
  120. body: {data: promptResponse},
  121. });
  122. render(
  123. <InviteBanner
  124. missingMembers={missingMembers}
  125. onSendInvite={() => undefined}
  126. organization={org}
  127. />
  128. );
  129. expect(
  130. await screen.findByRole('heading', {
  131. name: 'Bring your full GitHub team on board in Sentry',
  132. })
  133. ).toBeInTheDocument();
  134. });
  135. it('does not render banner if snoozed_ts days is shorter than threshold', function () {
  136. const org = TestStubs.Organization({
  137. features: ['integrations-gh-invite'],
  138. });
  139. const promptResponse = {
  140. dismissed_ts: undefined,
  141. snoozed_ts: moment
  142. .utc()
  143. .subtract(DEFAULT_SNOOZE_PROMPT_DAYS - 1, 'days')
  144. .unix(),
  145. };
  146. const mockPrompt = MockApiClient.addMockResponse({
  147. url: '/prompts-activity/',
  148. method: 'GET',
  149. body: {data: promptResponse},
  150. });
  151. render(
  152. <InviteBanner
  153. missingMembers={missingMembers}
  154. onSendInvite={() => undefined}
  155. organization={org}
  156. />
  157. );
  158. expect(mockPrompt).toHaveBeenCalled();
  159. expect(
  160. screen.queryByRole('heading', {
  161. name: 'Bring your full GitHub team on board in Sentry',
  162. })
  163. ).not.toBeInTheDocument();
  164. });
  165. });