inviteRequestRow.spec.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import {MemberFixture} from 'sentry-fixture/member';
  2. import {OrganizationFixture} from 'sentry-fixture/organization';
  3. import {TeamFixture} from 'sentry-fixture/team';
  4. import {UserFixture} from 'sentry-fixture/user';
  5. import {
  6. render,
  7. renderGlobalModal,
  8. screen,
  9. userEvent,
  10. } from 'sentry-test/reactTestingLibrary';
  11. import selectEvent from 'sentry-test/selectEvent';
  12. import TeamStore from 'sentry/stores/teamStore';
  13. import type {OrgRole} from 'sentry/types';
  14. import InviteRequestRow from 'sentry/views/settings/organizationMembers/inviteRequestRow';
  15. const roles: OrgRole[] = [
  16. {
  17. id: 'admin',
  18. name: 'Admin',
  19. desc: 'This is the admin role',
  20. minimumTeamRole: '',
  21. allowed: true,
  22. },
  23. {
  24. id: 'member',
  25. name: 'Member',
  26. desc: 'This is the member role',
  27. minimumTeamRole: '',
  28. allowed: true,
  29. },
  30. {
  31. id: 'owner',
  32. name: 'Owner',
  33. desc: 'This is the owner role',
  34. minimumTeamRole: '',
  35. allowed: false,
  36. },
  37. ];
  38. describe('InviteRequestRow', function () {
  39. const orgWithoutAdminAccess = OrganizationFixture({
  40. access: [],
  41. });
  42. const orgWithAdminAccess = OrganizationFixture({
  43. access: ['member:admin'],
  44. });
  45. const inviteRequestBusy: Record<string, boolean> = {};
  46. const inviteRequest = MemberFixture({
  47. user: null,
  48. inviterName: UserFixture().name,
  49. inviteStatus: 'requested_to_be_invited',
  50. role: 'member',
  51. teams: ['myteam'],
  52. });
  53. const joinRequest = MemberFixture({
  54. user: null,
  55. inviteStatus: 'requested_to_join',
  56. role: 'member',
  57. teams: ['myteam'],
  58. });
  59. it('renders request to be invited', function () {
  60. render(
  61. <InviteRequestRow
  62. organization={orgWithoutAdminAccess}
  63. inviteRequest={inviteRequest}
  64. inviteRequestBusy={inviteRequestBusy}
  65. onApprove={() => {}}
  66. onDeny={() => {}}
  67. onUpdate={() => {}}
  68. allRoles={roles}
  69. />
  70. );
  71. expect(screen.getByText(inviteRequest.email)).toBeInTheDocument();
  72. expect(
  73. screen.getByText(`Requested by ${inviteRequest.inviterName}`)
  74. ).toBeInTheDocument();
  75. });
  76. it('renders request to join', function () {
  77. render(
  78. <InviteRequestRow
  79. organization={orgWithoutAdminAccess}
  80. inviteRequest={joinRequest}
  81. inviteRequestBusy={inviteRequestBusy}
  82. onApprove={() => {}}
  83. onDeny={() => {}}
  84. onUpdate={() => {}}
  85. allRoles={roles}
  86. />
  87. );
  88. expect(screen.getByText(joinRequest.email)).toBeInTheDocument();
  89. expect(screen.getByRole('button', {name: 'Approve'})).toBeInTheDocument();
  90. expect(screen.getByRole('button', {name: 'Deny'})).toBeInTheDocument();
  91. });
  92. it('admin can approve invite request', async function () {
  93. const mockApprove = jest.fn();
  94. const mockDeny = jest.fn();
  95. render(
  96. <InviteRequestRow
  97. organization={orgWithAdminAccess}
  98. inviteRequest={inviteRequest}
  99. inviteRequestBusy={inviteRequestBusy}
  100. onApprove={mockApprove}
  101. onDeny={mockDeny}
  102. onUpdate={() => {}}
  103. allRoles={roles}
  104. />
  105. );
  106. await userEvent.click(screen.getByRole('button', {name: 'Approve'}));
  107. renderGlobalModal();
  108. await userEvent.click(screen.getByTestId('confirm-button'));
  109. expect(mockApprove).toHaveBeenCalledWith(inviteRequest);
  110. expect(mockDeny).not.toHaveBeenCalled();
  111. });
  112. it('admin can deny invite request', async function () {
  113. const mockApprove = jest.fn();
  114. const mockDeny = jest.fn();
  115. render(
  116. <InviteRequestRow
  117. organization={orgWithAdminAccess}
  118. inviteRequest={inviteRequest}
  119. inviteRequestBusy={inviteRequestBusy}
  120. onApprove={mockApprove}
  121. onDeny={mockDeny}
  122. onUpdate={() => {}}
  123. allRoles={roles}
  124. />
  125. );
  126. await userEvent.click(screen.getByRole('button', {name: 'Deny'}));
  127. expect(mockDeny).toHaveBeenCalledWith(inviteRequest);
  128. expect(mockApprove).not.toHaveBeenCalled();
  129. });
  130. it('non-admin can not approve or deny invite request', function () {
  131. render(
  132. <InviteRequestRow
  133. organization={orgWithoutAdminAccess}
  134. inviteRequest={inviteRequest}
  135. inviteRequestBusy={inviteRequestBusy}
  136. onApprove={() => {}}
  137. onDeny={() => {}}
  138. onUpdate={() => {}}
  139. allRoles={roles}
  140. />
  141. );
  142. expect(screen.getByRole('button', {name: 'Approve'})).toBeDisabled();
  143. expect(screen.getByRole('button', {name: 'Deny'})).toBeDisabled();
  144. });
  145. it('admin can change role and teams', async function () {
  146. const adminInviteRequest = MemberFixture({
  147. user: null,
  148. inviterName: UserFixture().name,
  149. inviteStatus: 'requested_to_be_invited',
  150. role: 'admin',
  151. teams: ['myteam'],
  152. });
  153. void TeamStore.loadInitialData([
  154. TeamFixture({id: '1', slug: 'one'}),
  155. TeamFixture({id: '2', slug: 'two'}),
  156. ]);
  157. const mockUpdate = jest.fn();
  158. render(
  159. <InviteRequestRow
  160. organization={orgWithAdminAccess}
  161. inviteRequest={adminInviteRequest}
  162. inviteRequestBusy={inviteRequestBusy}
  163. onApprove={() => {}}
  164. onDeny={() => {}}
  165. onUpdate={mockUpdate}
  166. allRoles={roles}
  167. />
  168. );
  169. // Select role from first select input
  170. await selectEvent.select(screen.getAllByRole('textbox')[0], 'Member');
  171. expect(mockUpdate).toHaveBeenCalledWith({role: 'member'});
  172. // Select teams from first select input
  173. await selectEvent.select(screen.getAllByRole('textbox')[1], ['#one']);
  174. expect(mockUpdate).toHaveBeenCalledWith({teams: ['one']});
  175. TeamStore.reset();
  176. });
  177. it('cannot be approved when invitee role is not allowed', function () {
  178. const ownerInviteRequest = MemberFixture({
  179. user: null,
  180. inviterName: UserFixture().name,
  181. inviteStatus: 'requested_to_be_invited',
  182. role: 'owner',
  183. teams: ['myteam'],
  184. });
  185. const mockUpdate = jest.fn();
  186. render(
  187. <InviteRequestRow
  188. organization={orgWithoutAdminAccess}
  189. inviteRequest={ownerInviteRequest}
  190. inviteRequestBusy={inviteRequestBusy}
  191. onApprove={() => {}}
  192. onDeny={() => {}}
  193. onUpdate={mockUpdate}
  194. allRoles={roles}
  195. />
  196. );
  197. expect(screen.getByRole('button', {name: 'Approve'})).toBeDisabled();
  198. });
  199. });