organizationMemberRow.spec.jsx 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. import {render, screen} from 'sentry-test/reactTestingLibrary';
  2. import OrganizationMemberRow from 'sentry/views/settings/organizationMembers/organizationMemberRow';
  3. describe('OrganizationMemberRow', function () {
  4. const member = {
  5. id: '1',
  6. email: '',
  7. name: '',
  8. role: 'member',
  9. roleName: 'Member',
  10. pending: false,
  11. flags: {
  12. 'sso:linked': false,
  13. },
  14. user: {
  15. id: '',
  16. has2fa: false,
  17. name: 'sentry@test.com',
  18. },
  19. };
  20. const currentUser = {
  21. id: '2',
  22. email: 'currentUser@email.com',
  23. };
  24. const defaultProps = {
  25. routes: [],
  26. orgId: 'org-slug',
  27. orgName: 'Organization Name',
  28. status: '',
  29. requireLink: false,
  30. memberCanLeave: false,
  31. canAddMembers: false,
  32. canRemoveMembers: false,
  33. member,
  34. currentUser,
  35. onSendInvite: () => {},
  36. onRemove: () => {},
  37. onLeave: () => {},
  38. };
  39. function resendButton() {
  40. return screen.queryByRole('button', {name: 'Resend invite'});
  41. }
  42. function resendSsoButton() {
  43. return screen.queryByRole('button', {name: 'Resend SSO link'});
  44. }
  45. function leaveButton() {
  46. return screen.queryByRole('button', {name: 'Leave'});
  47. }
  48. function removeButton() {
  49. return screen.queryByRole('button', {name: 'Remove'});
  50. }
  51. describe('two factor', function () {
  52. it('does not have 2fa warning if user has 2fa', function () {
  53. render(
  54. <OrganizationMemberRow
  55. {...defaultProps}
  56. member={{
  57. ...member,
  58. user: {...member.user, has2fa: true},
  59. }}
  60. />
  61. );
  62. expect(screen.getByText('2FA Enabled')).toBeInTheDocument();
  63. expect(screen.queryByText('2FA Not Enabled')).not.toBeInTheDocument();
  64. });
  65. it('has 2fa warning if user does not have 2fa enabled', function () {
  66. render(
  67. <OrganizationMemberRow
  68. {...defaultProps}
  69. member={{
  70. ...member,
  71. user: {...member.user, has2fa: false},
  72. }}
  73. />
  74. );
  75. expect(screen.getByText('2FA Not Enabled')).toBeInTheDocument();
  76. expect(screen.queryByText('2FA Enabled')).not.toBeInTheDocument();
  77. });
  78. });
  79. describe('Pending user', function () {
  80. const props = {
  81. ...defaultProps,
  82. member: {...member, pending: true},
  83. };
  84. it('has "Invited" status, no "Resend Invite"', function () {
  85. render(<OrganizationMemberRow {...props} />);
  86. expect(screen.getByTestId('member-role')).toHaveTextContent('Invited Member');
  87. expect(resendButton()).toBeDisabled();
  88. });
  89. it('has "Resend Invite" button only if `canAddMembers` is true', function () {
  90. render(<OrganizationMemberRow {...props} canAddMembers />);
  91. expect(screen.getByTestId('member-role')).toHaveTextContent('Invited Member');
  92. expect(resendButton()).toBeEnabled();
  93. });
  94. it('has the right inviting states', function () {
  95. render(<OrganizationMemberRow {...props} canAddMembers />);
  96. expect(resendButton()).toBeInTheDocument();
  97. });
  98. it('has loading state', function () {
  99. render(<OrganizationMemberRow {...props} canAddMembers status="loading" />);
  100. // Should have loader
  101. expect(screen.getByTestId('loading-indicator')).toBeInTheDocument();
  102. // No Resend Invite button
  103. expect(resendButton()).not.toBeInTheDocument();
  104. });
  105. it('has success status', function () {
  106. render(<OrganizationMemberRow {...props} canAddMembers status="success" />);
  107. // Should not have loader
  108. expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument();
  109. // No Resend Invite button
  110. expect(resendButton()).not.toBeInTheDocument();
  111. expect(screen.getByTestId('member-status')).toHaveTextContent('Sent!');
  112. });
  113. });
  114. describe('Expired user', function () {
  115. it('has "Expired" status', function () {
  116. render(
  117. <OrganizationMemberRow
  118. {...defaultProps}
  119. canAddMembers
  120. member={{...member, pending: true, expired: true}}
  121. />
  122. );
  123. expect(screen.getByTestId('member-role')).toHaveTextContent('Expired Invite');
  124. expect(resendButton()).toBeEnabled();
  125. });
  126. });
  127. describe('Requires SSO Link', function () {
  128. const props = {
  129. ...defaultProps,
  130. flags: {'sso:link': false},
  131. requireLink: true,
  132. };
  133. it('shows "Invited" status if user has not registered and not linked', function () {
  134. render(
  135. <OrganizationMemberRow
  136. {...props}
  137. canAddMembers
  138. member={{...member, pending: true}}
  139. />
  140. );
  141. expect(screen.getByTestId('member-role')).toHaveTextContent('Invited Member');
  142. expect(resendButton()).toBeEnabled();
  143. });
  144. it('shows "missing SSO link" message if user is registered and needs link', function () {
  145. render(<OrganizationMemberRow {...props} />);
  146. expect(screen.getByTestId('member-role')).toHaveTextContent('Member');
  147. expect(resendSsoButton()).toBeDisabled();
  148. });
  149. it('has "Resend SSO link" button only if `canAddMembers` is true and no link', function () {
  150. render(<OrganizationMemberRow {...props} canAddMembers />);
  151. expect(resendSsoButton()).toBeEnabled();
  152. });
  153. it('has 2fa warning if user is linked does not have 2fa enabled', function () {
  154. render(
  155. <OrganizationMemberRow
  156. {...defaultProps}
  157. member={{
  158. ...member,
  159. flags: {'sso:linked': true},
  160. user: {...member.user, has2fa: false},
  161. }}
  162. />
  163. );
  164. expect(screen.getByText('2FA Not Enabled')).toBeInTheDocument();
  165. expect(screen.queryByText('2FA Enabled')).not.toBeInTheDocument();
  166. });
  167. });
  168. describe('Is Current User', function () {
  169. const props = {
  170. ...defaultProps,
  171. member: {
  172. ...member,
  173. email: 'currentUser@email.com',
  174. },
  175. };
  176. it('has button to leave organization and no button to remove', function () {
  177. render(<OrganizationMemberRow {...props} memberCanLeave />);
  178. expect(leaveButton()).toBeInTheDocument();
  179. expect(removeButton()).not.toBeInTheDocument();
  180. });
  181. it('has disabled button to leave organization and no button to remove when member can not leave', function () {
  182. render(<OrganizationMemberRow {...props} memberCanLeave={false} />);
  183. expect(leaveButton()).toBeDisabled();
  184. expect(removeButton()).not.toBeInTheDocument();
  185. });
  186. });
  187. describe('Not Current User', function () {
  188. const props = {
  189. ...defaultProps,
  190. };
  191. it('does not have Leave button', function () {
  192. render(<OrganizationMemberRow {...props} memberCanLeave />);
  193. expect(leaveButton()).not.toBeInTheDocument();
  194. });
  195. it('has Remove disabled button when `canRemoveMembers` is false', function () {
  196. render(<OrganizationMemberRow {...props} />);
  197. expect(removeButton()).toBeDisabled();
  198. });
  199. it('has Remove button when `canRemoveMembers` is true', function () {
  200. render(<OrganizationMemberRow {...props} canRemoveMembers />);
  201. expect(removeButton()).toBeEnabled();
  202. });
  203. });
  204. });