inviteBanner.spec.tsx 4.9 KB

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