mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-26 18:51:50 +02:00
Merge pull request #15348 from overleaf/ab-decoupling-refactor-members-table
[web] Modular members management table refactoring GitOrigin-RevId: 9a3a00a32970e78e5b43b3a68621a627c490c728
This commit is contained in:
committed by
Copybot
parent
0ed80e9f44
commit
1d43dcc5c1
@@ -1074,6 +1074,7 @@
|
||||
"source": "",
|
||||
"spell_check": "",
|
||||
"sso": "",
|
||||
"sso_active": "",
|
||||
"sso_config_prop_help_certificate": "",
|
||||
"sso_config_prop_help_first_name": "",
|
||||
"sso_config_prop_help_last_name": "",
|
||||
@@ -1092,9 +1093,8 @@
|
||||
"sso_is_enabled_explanation_2": "",
|
||||
"sso_link_error": "",
|
||||
"sso_link_invite_has_been_sent_to_email": "",
|
||||
"sso_linked": "",
|
||||
"sso_logs": "",
|
||||
"sso_unlinked": "",
|
||||
"sso_not_active": "",
|
||||
"start_a_free_trial": "",
|
||||
"start_by_adding_your_email": "",
|
||||
"start_free_trial": "",
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
import { useCallback } from 'react'
|
||||
import { Col, Row } from 'react-bootstrap'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '../../../shared/components/tooltip'
|
||||
import { useGroupMembersContext } from '../context/group-members-context'
|
||||
import GroupMemberRow from './group-member-row'
|
||||
|
||||
export default function GroupMembersList() {
|
||||
const { t } = useTranslation()
|
||||
const {
|
||||
selectedUsers,
|
||||
users,
|
||||
selectUser,
|
||||
unselectUser,
|
||||
selectAllUsers,
|
||||
unselectAllUsers,
|
||||
} = useGroupMembersContext()
|
||||
|
||||
const handleSelectAllClick = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.checked) {
|
||||
selectAllUsers()
|
||||
} else {
|
||||
unselectAllUsers()
|
||||
}
|
||||
},
|
||||
[selectAllUsers, unselectAllUsers]
|
||||
)
|
||||
|
||||
return (
|
||||
<ul className="list-unstyled structured-list">
|
||||
<li className="container-fluid">
|
||||
<Row>
|
||||
<Col xs={4}>
|
||||
<label htmlFor="select-all" className="sr-only">
|
||||
{t('select_all')}
|
||||
</label>
|
||||
<input
|
||||
className="select-all"
|
||||
id="select-all"
|
||||
type="checkbox"
|
||||
onChange={handleSelectAllClick}
|
||||
checked={selectedUsers.length === users.length}
|
||||
/>
|
||||
<span className="header">{t('email')}</span>
|
||||
</Col>
|
||||
<Col xs={4}>
|
||||
<span className="header">{t('name')}</span>
|
||||
</Col>
|
||||
<Col xs={2}>
|
||||
<Tooltip
|
||||
id="last-active-tooltip"
|
||||
description={t('last_active_description')}
|
||||
overlayProps={{
|
||||
placement: 'left',
|
||||
}}
|
||||
>
|
||||
<span className="header">
|
||||
{t('last_active')}
|
||||
<sup>(?)</sup>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Col>
|
||||
<Col xs={2}>
|
||||
<span className="header">{t('accepted_invite')}</span>
|
||||
</Col>
|
||||
</Row>
|
||||
</li>
|
||||
{users.length === 0 && (
|
||||
<li>
|
||||
<Row>
|
||||
<Col md={12} className="text-centered">
|
||||
<small>{t('no_members')}</small>
|
||||
</Col>
|
||||
</Row>
|
||||
</li>
|
||||
)}
|
||||
{users.map((user: any) => (
|
||||
<GroupMemberRow
|
||||
key={user.email}
|
||||
user={user}
|
||||
selectUser={selectUser}
|
||||
unselectUser={unselectUser}
|
||||
selected={selectedUsers.includes(user)}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
@@ -6,8 +6,7 @@ import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
|
||||
import getMeta from '../../../utils/meta'
|
||||
import { useGroupMembersContext } from '../context/group-members-context'
|
||||
import ErrorAlert from './error-alert'
|
||||
import ManagedUsersList from './managed-users/managed-users-list'
|
||||
import GroupMembersList from './group-members-list'
|
||||
import MembersList from './members-table/members-list'
|
||||
|
||||
export default function GroupMembers() {
|
||||
const { isReady } = useWaitForI18n()
|
||||
@@ -28,7 +27,6 @@ export default function GroupMembers() {
|
||||
const groupId: string = getMeta('ol-groupId')
|
||||
const groupName: string = getMeta('ol-groupName')
|
||||
const groupSize: number = getMeta('ol-groupSize')
|
||||
const managedUsersActive: any = getMeta('ol-managedUsersActive')
|
||||
|
||||
const handleEmailsChange = useCallback(
|
||||
e => {
|
||||
@@ -91,11 +89,7 @@ export default function GroupMembers() {
|
||||
</div>
|
||||
<div className="row-spaced-small">
|
||||
<ErrorAlert error={removeMemberError} />
|
||||
{managedUsersActive ? (
|
||||
<ManagedUsersList groupId={groupId} />
|
||||
) : (
|
||||
<GroupMembersList />
|
||||
)}
|
||||
<MembersList groupId={groupId} />
|
||||
</div>
|
||||
<hr />
|
||||
{users.length < groupSize && (
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
import { useCallback, useState } from 'react'
|
||||
import { Button, Col, Form, FormControl, Row } from 'react-bootstrap'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
deleteJSON,
|
||||
FetchError,
|
||||
postJSON,
|
||||
} from '../../../infrastructure/fetch-json'
|
||||
import { deleteJSON, FetchError, postJSON } from '@/infrastructure/fetch-json'
|
||||
import MaterialIcon from '../../../shared/components/material-icon'
|
||||
import Tooltip from '../../../shared/components/tooltip'
|
||||
import getMeta from '../../../utils/meta'
|
||||
import { parseEmails } from '../utils/emails'
|
||||
import ErrorAlert, { APIError } from './error-alert'
|
||||
import GroupMemberRow from './group-member-row'
|
||||
import UserRow from './user-row'
|
||||
import useUserSelection from '../hooks/use-user-selection'
|
||||
import { User } from '../../../../../types/group-management/user'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
@@ -216,7 +212,7 @@ export function ManagersTable({
|
||||
</li>
|
||||
)}
|
||||
{users.map(user => (
|
||||
<GroupMemberRow
|
||||
<UserRow
|
||||
key={user.email}
|
||||
user={user}
|
||||
selectUser={selectUser}
|
||||
|
||||
@@ -8,12 +8,9 @@ import {
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Dropdown, MenuItem } from 'react-bootstrap'
|
||||
import { User } from '../../../../../../types/group-management/user'
|
||||
import useAsync from '../../../../shared/hooks/use-async'
|
||||
import {
|
||||
type FetchError,
|
||||
postJSON,
|
||||
} from '../../../../infrastructure/fetch-json'
|
||||
import Icon from '../../../../shared/components/icon'
|
||||
import useAsync from '@/shared/hooks/use-async'
|
||||
import { type FetchError, postJSON } from '@/infrastructure/fetch-json'
|
||||
import Icon from '@/shared/components/icon'
|
||||
import { ManagedUserAlert } from '../../utils/types'
|
||||
import { useGroupMembersContext } from '../../context/group-members-context'
|
||||
import getMeta from '@/utils/meta'
|
||||
@@ -28,7 +25,7 @@ type ManagedUserDropdownButtonProps = {
|
||||
setManagedUserAlert: Dispatch<SetStateAction<ManagedUserAlert>>
|
||||
}
|
||||
|
||||
export default function ManagedUserDropdownButton({
|
||||
export default function DropdownButton({
|
||||
user,
|
||||
openOffboardingModalForUser,
|
||||
groupId,
|
||||
@@ -9,7 +9,7 @@ type ManagedUsersListAlertProps = {
|
||||
onDismiss: () => void
|
||||
}
|
||||
|
||||
export default function ManagedUsersListAlert({
|
||||
export default function ListAlert({
|
||||
variant,
|
||||
invitedUserEmail,
|
||||
onDismiss,
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { User } from '../../../../../../types/group-management/user'
|
||||
import MaterialIcon from '../../../../shared/components/material-icon'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
|
||||
type ManagedUserStatusProps = {
|
||||
user: User
|
||||
@@ -7,8 +7,8 @@ import Tooltip from '../../../../shared/components/tooltip'
|
||||
import type { ManagedUserAlert } from '../../utils/types'
|
||||
import ManagedUserStatus from './managed-user-status'
|
||||
import SSOStatus from './sso-status'
|
||||
import ManagedUserDropdownButton from './managed-user-dropdown-button'
|
||||
import ManagedUsersSelectUserCheckbox from './managed-users-select-user-checkbox'
|
||||
import DropdownButton from './dropdown-button'
|
||||
import SelectUserCheckbox from './select-user-checkbox'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
type ManagedUserRowProps = {
|
||||
@@ -18,13 +18,14 @@ type ManagedUserRowProps = {
|
||||
setManagedUserAlert: Dispatch<SetStateAction<ManagedUserAlert>>
|
||||
}
|
||||
|
||||
export default function ManagedUserRow({
|
||||
export default function MemberRow({
|
||||
user,
|
||||
openOffboardingModalForUser,
|
||||
setManagedUserAlert,
|
||||
groupId,
|
||||
}: ManagedUserRowProps) {
|
||||
const { t } = useTranslation()
|
||||
const managedUsersActive: any = getMeta('ol-managedUsersActive')
|
||||
const groupSSOActive = getMeta('ol-groupSSOActive')
|
||||
|
||||
return (
|
||||
@@ -32,8 +33,8 @@ export default function ManagedUserRow({
|
||||
key={`user-${user.email}`}
|
||||
className={`managed-user-row ${user.invite ? 'text-muted' : ''}`}
|
||||
>
|
||||
<ManagedUsersSelectUserCheckbox user={user} />
|
||||
<td className={groupSSOActive ? 'cell-email-with-sso-col' : 'cell-email'}>
|
||||
<SelectUserCheckbox user={user} />
|
||||
<td className="cell-email">
|
||||
<span>
|
||||
{user.email}
|
||||
{user.invite ? (
|
||||
@@ -83,13 +84,15 @@ export default function ManagedUserRow({
|
||||
</div>
|
||||
</td>
|
||||
)}
|
||||
<td className="cell-managed">
|
||||
<div className="managed-user-security">
|
||||
<ManagedUserStatus user={user} />
|
||||
</div>
|
||||
</td>
|
||||
{managedUsersActive && (
|
||||
<td className="cell-managed">
|
||||
<div className="managed-user-security">
|
||||
<ManagedUserStatus user={user} />
|
||||
</div>
|
||||
</td>
|
||||
)}
|
||||
<td className="cell-dropdown">
|
||||
<ManagedUserDropdownButton
|
||||
<DropdownButton
|
||||
user={user}
|
||||
openOffboardingModalForUser={openOffboardingModalForUser}
|
||||
setManagedUserAlert={setManagedUserAlert}
|
||||
@@ -2,20 +2,21 @@ import { useState } from 'react'
|
||||
import { Col, Row } from 'react-bootstrap'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { User } from '../../../../../../types/group-management/user'
|
||||
import Tooltip from '../../../../shared/components/tooltip'
|
||||
import Tooltip from '@/shared/components/tooltip'
|
||||
import { useGroupMembersContext } from '../../context/group-members-context'
|
||||
import type { ManagedUserAlert } from '../../utils/types'
|
||||
import ManagedUserRow from './managed-user-row'
|
||||
import MemberRow from './member-row'
|
||||
import OffboardManagedUserModal from './offboard-managed-user-modal'
|
||||
import ManagedUsersListAlert from './managed-users-list-alert'
|
||||
import ManagedUsersSelectAllCheckbox from './managed-users-select-all-checkbox'
|
||||
import ListAlert from './list-alert'
|
||||
import SelectAllCheckbox from './select-all-checkbox'
|
||||
import classNames from 'classnames'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
type ManagedUsersListProps = {
|
||||
groupId: string
|
||||
}
|
||||
|
||||
export default function ManagedUsersList({ groupId }: ManagedUsersListProps) {
|
||||
export default function MembersList({ groupId }: ManagedUsersListProps) {
|
||||
const { t } = useTranslation()
|
||||
const [userToOffboard, setUserToOffboard] = useState<User | undefined>(
|
||||
undefined
|
||||
@@ -23,32 +24,37 @@ export default function ManagedUsersList({ groupId }: ManagedUsersListProps) {
|
||||
const [managedUserAlert, setManagedUserAlert] =
|
||||
useState<ManagedUserAlert>(undefined)
|
||||
const { users } = useGroupMembersContext()
|
||||
const managedUsersActive: any = getMeta('ol-managedUsersActive')
|
||||
const groupSSOActive = getMeta('ol-groupSSOActive')
|
||||
|
||||
return (
|
||||
<div>
|
||||
{managedUserAlert && (
|
||||
<ManagedUsersListAlert
|
||||
{managedUsersActive && managedUserAlert && (
|
||||
<ListAlert
|
||||
variant={managedUserAlert.variant}
|
||||
invitedUserEmail={managedUserAlert.email}
|
||||
onDismiss={() => setManagedUserAlert(undefined)}
|
||||
/>
|
||||
)}
|
||||
<ul className="list-unstyled structured-list managed-users-list">
|
||||
<ul
|
||||
className={classNames(
|
||||
'list-unstyled',
|
||||
'structured-list',
|
||||
'managed-users-list',
|
||||
{
|
||||
'managed-users-active': managedUsersActive,
|
||||
'group-sso-active': groupSSOActive,
|
||||
}
|
||||
)}
|
||||
>
|
||||
<li className="container-fluid">
|
||||
<Row id="managed-users-list-headers">
|
||||
<Col xs={12}>
|
||||
<table className="managed-users-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<ManagedUsersSelectAllCheckbox />
|
||||
<td
|
||||
className={
|
||||
groupSSOActive
|
||||
? 'cell-email-with-sso-col'
|
||||
: 'cell-email'
|
||||
}
|
||||
>
|
||||
<SelectAllCheckbox />
|
||||
<td className="cell-email">
|
||||
<span className="header">{t('email')}</span>
|
||||
</td>
|
||||
<td className="cell-name">
|
||||
@@ -73,9 +79,11 @@ export default function ManagedUsersList({ groupId }: ManagedUsersListProps) {
|
||||
<span className="header">{t('security')}</span>
|
||||
</td>
|
||||
)}
|
||||
<td className="cell-managed">
|
||||
<span className="header">{t('managed')}</span>
|
||||
</td>
|
||||
{managedUsersActive && (
|
||||
<td className="cell-managed">
|
||||
<span className="header">{t('managed')}</span>
|
||||
</td>
|
||||
)}
|
||||
<td />
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -88,7 +96,7 @@ export default function ManagedUsersList({ groupId }: ManagedUsersListProps) {
|
||||
</tr>
|
||||
)}
|
||||
{users.map((user: any) => (
|
||||
<ManagedUserRow
|
||||
<MemberRow
|
||||
key={user.email}
|
||||
user={user}
|
||||
openOffboardingModalForUser={setUserToOffboard}
|
||||
@@ -8,13 +8,13 @@ import {
|
||||
FormGroup,
|
||||
Modal,
|
||||
} from 'react-bootstrap'
|
||||
import AccessibleModal from '../../../../shared/components/accessible-modal'
|
||||
import Icon from '../../../../shared/components/icon'
|
||||
import AccessibleModal from '@/shared/components/accessible-modal'
|
||||
import Icon from '@/shared/components/icon'
|
||||
import { useState } from 'react'
|
||||
import useAsync from '../../../../shared/hooks/use-async'
|
||||
import useAsync from '@/shared/hooks/use-async'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useLocation } from '../../../../shared/hooks/use-location'
|
||||
import { FetchError, postJSON } from '../../../../infrastructure/fetch-json'
|
||||
import { useLocation } from '@/shared/hooks/use-location'
|
||||
import { FetchError, postJSON } from '@/infrastructure/fetch-json'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
|
||||
type OffboardManagedUserModalProps = {
|
||||
@@ -1,11 +1,9 @@
|
||||
import { useCallback } from 'react'
|
||||
import React, { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useGroupMembersContext } from '../../context/group-members-context'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
export default function ManagedUsersSelectAllCheckbox() {
|
||||
export default function SelectAllCheckbox() {
|
||||
const { t } = useTranslation()
|
||||
const groupSSOActive = getMeta('ol-groupSSOActive')
|
||||
|
||||
const { selectedUsers, users, selectAllNonManagedUsers, unselectAllUsers } =
|
||||
useGroupMembersContext()
|
||||
@@ -30,11 +28,7 @@ export default function ManagedUsersSelectAllCheckbox() {
|
||||
}
|
||||
|
||||
return (
|
||||
<td
|
||||
className={
|
||||
groupSSOActive ? 'cell-checkbox-with-sso-col ' : 'cell-checkbox'
|
||||
}
|
||||
>
|
||||
<td className="cell-checkbox">
|
||||
<label htmlFor="select-all" className="sr-only">
|
||||
{t('select_all')}
|
||||
</label>
|
||||
@@ -2,17 +2,15 @@ import { useTranslation } from 'react-i18next'
|
||||
import type { User } from '../../../../../../types/group-management/user'
|
||||
import { useGroupMembersContext } from '../../context/group-members-context'
|
||||
import { useCallback } from 'react'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
type ManagedUsersSelectUserCheckboxProps = {
|
||||
user: User
|
||||
}
|
||||
|
||||
export default function ManagedUsersSelectUserCheckbox({
|
||||
export default function SelectUserCheckbox({
|
||||
user,
|
||||
}: ManagedUsersSelectUserCheckboxProps) {
|
||||
const { t } = useTranslation()
|
||||
const groupSSOActive = getMeta('ol-groupSSOActive')
|
||||
const { users, selectedUsers, selectUser, unselectUser } =
|
||||
useGroupMembersContext()
|
||||
|
||||
@@ -40,11 +38,7 @@ export default function ManagedUsersSelectUserCheckbox({
|
||||
const selected = selectedUsers.includes(user)
|
||||
|
||||
return (
|
||||
<td
|
||||
className={
|
||||
groupSSOActive ? 'cell-checkbox-with-sso-col ' : 'cell-checkbox'
|
||||
}
|
||||
>
|
||||
<td className="cell-checkbox">
|
||||
{/* the next check will hide the `checkbox` but still show the `td` */}
|
||||
{user.enrollment?.managedBy ? null : (
|
||||
<>
|
||||
@@ -19,13 +19,13 @@ export default function SSOStatus({ user }: SSOStatusProps) {
|
||||
)
|
||||
const acceptedSSO = (
|
||||
<span className="security-state-managed">
|
||||
<MaterialIcon type="check" accessibilityLabel={t('sso_linked')} />
|
||||
<MaterialIcon type="check" accessibilityLabel={t('sso_active')} />
|
||||
{t('sso')}
|
||||
</span>
|
||||
)
|
||||
const notAcceptedSSO = (
|
||||
<span className="security-state-not-managed">
|
||||
<MaterialIcon type="close" accessibilityLabel={t('sso_unlinked')} />
|
||||
<MaterialIcon type="close" accessibilityLabel={t('sso_not_active')} />
|
||||
{t('sso')}
|
||||
</span>
|
||||
)
|
||||
@@ -11,7 +11,7 @@ type GroupMemberRowProps = {
|
||||
selected: boolean
|
||||
}
|
||||
|
||||
export default function GroupMemberRow({
|
||||
export default function UserRow({
|
||||
user,
|
||||
selectUser,
|
||||
unselectUser,
|
||||
@@ -7,13 +7,9 @@ import {
|
||||
useState,
|
||||
} from 'react'
|
||||
import { User } from '../../../../../types/group-management/user'
|
||||
import {
|
||||
deleteJSON,
|
||||
FetchError,
|
||||
postJSON,
|
||||
} from '../../../infrastructure/fetch-json'
|
||||
import { mapSeries } from '../../../infrastructure/promise'
|
||||
import getMeta from '../../../utils/meta'
|
||||
import { deleteJSON, FetchError, postJSON } from '@/infrastructure/fetch-json'
|
||||
import { mapSeries } from '@/infrastructure/promise'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { APIError } from '../components/error-alert'
|
||||
import useUserSelection from '../hooks/use-user-selection'
|
||||
import { parseEmails } from '../utils/emails'
|
||||
|
||||
@@ -103,75 +103,39 @@
|
||||
}
|
||||
}
|
||||
|
||||
.cell-checkbox {
|
||||
width: 5%;
|
||||
}
|
||||
.cell-checkbox-with-sso-col {
|
||||
width: 2.5%;
|
||||
}
|
||||
|
||||
.cell-email {
|
||||
width: 45%;
|
||||
}
|
||||
.cell-email-with-sso-col {
|
||||
width: 37%;
|
||||
}
|
||||
|
||||
.cell-name {
|
||||
width: 15%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.cell-last-active {
|
||||
width: 15%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.cell-security {
|
||||
width: 10%;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.cell-managed {
|
||||
width: 15%;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.cell-dropdown {
|
||||
width: 5%;
|
||||
min-width: 25px;
|
||||
}
|
||||
|
||||
@media (min-width: @screen-xs) {
|
||||
.cell-checkbox {
|
||||
width: 5%;
|
||||
}
|
||||
|
||||
.cell-checkbox-with-sso-col {
|
||||
width: 2.5%;
|
||||
.managed-users-active.group-sso-active & {
|
||||
width: 3%;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-email {
|
||||
width: 34%;
|
||||
}
|
||||
.cell-email-with-sso-col {
|
||||
width: 29%;
|
||||
width: 50%;
|
||||
.managed-users-active & {
|
||||
width: 35%;
|
||||
}
|
||||
.group-sso-active & {
|
||||
width: 37%;
|
||||
}
|
||||
.managed-users-active.group-sso-active & {
|
||||
width: 29%;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-name {
|
||||
width: 20%;
|
||||
.managed-users-active.group-sso-active & {
|
||||
width: 18%;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-last-active {
|
||||
width: 20%;
|
||||
.managed-users-active.group-sso-active & {
|
||||
width: 16%;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-security {
|
||||
@@ -191,20 +155,28 @@
|
||||
@media (min-width: @screen-lg) {
|
||||
.cell-checkbox {
|
||||
width: 5%;
|
||||
.managed-users-active.group-sso-active & {
|
||||
width: 3%;
|
||||
}
|
||||
}
|
||||
.cell-checkbox-with-sso-col {
|
||||
width: 2.5%;
|
||||
}
|
||||
|
||||
.cell-email {
|
||||
width: 43%;
|
||||
}
|
||||
.cell-email-with-sso-col {
|
||||
width: 37%;
|
||||
width: 55%;
|
||||
.managed-users-active & {
|
||||
width: 42%;
|
||||
}
|
||||
.group-sso-active & {
|
||||
width: 45%;
|
||||
}
|
||||
.managed-users-active.group-sso-active & {
|
||||
width: 36%;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-name {
|
||||
width: 20%;
|
||||
.managed-users-active.group-sso-active & {
|
||||
width: 18%;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-last-active {
|
||||
@@ -216,7 +188,7 @@
|
||||
}
|
||||
|
||||
.cell-managed {
|
||||
width: 12%;
|
||||
width: 13%;
|
||||
}
|
||||
|
||||
.cell-dropdown {
|
||||
|
||||
@@ -1644,6 +1644,7 @@
|
||||
"spread_the_word_and_fill_bar": "Spread the word and fill this bar up",
|
||||
"sso": "SSO",
|
||||
"sso_account_already_linked": "Account already linked to another __appName__ user",
|
||||
"sso_active": "SSO active",
|
||||
"sso_config_prop_help_certificate": "Base64 encoded certificate without whitespace",
|
||||
"sso_config_prop_help_first_name": "Property in SAML assertion to use for first name",
|
||||
"sso_config_prop_help_last_name": "Property in SAML assertion to use for last name",
|
||||
@@ -1664,10 +1665,9 @@
|
||||
"sso_is_enabled_explanation_2": "If there are any problems with the configuration, only you (as the group administrator) will be able to disable SSO.",
|
||||
"sso_link_error": "Error linking account",
|
||||
"sso_link_invite_has_been_sent_to_email": "An SSO invite reminder has been sent to <0>__email__</0>",
|
||||
"sso_linked": "SSO linked",
|
||||
"sso_logs": "SSO Logs",
|
||||
"sso_not_active": "SSO not active",
|
||||
"sso_not_linked": "You have not linked your account to __provider__. Please log in to your account another way and link your __provider__ account via your account settings.",
|
||||
"sso_unlinked": "SSO unlinked",
|
||||
"sso_user_denied_access": "Cannot log in because __appName__ was not granted access to your __provider__ account. Please try again.",
|
||||
"standard": "Standard",
|
||||
"start_a_free_trial": "Start a free trial",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import GroupManagers from '../../../../../frontend/js/features/group-management/components/group-managers'
|
||||
import GroupManagers from '@/features/group-management/components/group-managers'
|
||||
|
||||
const JOHN_DOE = {
|
||||
_id: 'abc123def456',
|
||||
|
||||
@@ -1,22 +1,6 @@
|
||||
import GroupMembers from '../../../../../frontend/js/features/group-management/components/group-members'
|
||||
import { GroupMembersProvider } from '../../../../../frontend/js/features/group-management/context/group-members-context'
|
||||
import GroupMembers from '@/features/group-management/components/group-members'
|
||||
import { GroupMembersProvider } from '@/features/group-management/context/group-members-context'
|
||||
|
||||
const JOHN_DOE = {
|
||||
_id: 'abc123def456',
|
||||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
email: 'john.doe@test.com',
|
||||
last_active_at: new Date('2023-01-15'),
|
||||
invite: true,
|
||||
}
|
||||
const BOBBY_LAPOINTE = {
|
||||
_id: 'bcd234efa567',
|
||||
first_name: 'Bobby',
|
||||
last_name: 'Lapointe',
|
||||
email: 'bobby.lapointe@test.com',
|
||||
last_active_at: new Date('2023-01-02'),
|
||||
invite: false,
|
||||
}
|
||||
const GROUP_ID = '777fff777fff'
|
||||
const PATHS = {
|
||||
addMember: `/manage/groups/${GROUP_ID}/invites`,
|
||||
@@ -25,139 +9,436 @@ const PATHS = {
|
||||
exportMembers: `/manage/groups/${GROUP_ID}/members/export`,
|
||||
}
|
||||
|
||||
describe('group members, without managed users', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupId', GROUP_ID)
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Team')
|
||||
win.metaAttributesCache.set('ol-groupSize', 10)
|
||||
win.metaAttributesCache.set('ol-users', [JOHN_DOE, BOBBY_LAPOINTE])
|
||||
})
|
||||
|
||||
describe('GroupMembers', function () {
|
||||
function mountGroupMembersProvider() {
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<GroupMembers />
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
it('renders the group members page', function () {
|
||||
cy.get('h1').contains('My Awesome Team')
|
||||
cy.get('small').contains('You have added 2 of 10 available members')
|
||||
describe('with Managed Users and Group SSO disabled', function () {
|
||||
const JOHN_DOE = {
|
||||
_id: 'abc123def456',
|
||||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
email: 'john.doe@test.com',
|
||||
last_active_at: new Date('2023-01-15'),
|
||||
invite: true,
|
||||
}
|
||||
const BOBBY_LAPOINTE = {
|
||||
_id: 'bcd234efa567',
|
||||
first_name: 'Bobby',
|
||||
last_name: 'Lapointe',
|
||||
email: 'bobby.lapointe@test.com',
|
||||
last_active_at: new Date('2023-01-02'),
|
||||
invite: false,
|
||||
}
|
||||
|
||||
cy.get('ul').within(() => {
|
||||
cy.get('li:nth-child(2)').within(() => {
|
||||
cy.contains('john.doe@test.com')
|
||||
cy.contains('John Doe')
|
||||
cy.contains('15th Jan 2023')
|
||||
cy.get(`[aria-label="Invite not yet accepted"]`)
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupId', GROUP_ID)
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Team')
|
||||
win.metaAttributesCache.set('ol-groupSize', 10)
|
||||
win.metaAttributesCache.set('ol-users', [JOHN_DOE, BOBBY_LAPOINTE])
|
||||
})
|
||||
|
||||
cy.get('li:nth-child(3)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.contains('Bobby Lapointe')
|
||||
cy.contains('2nd Jan 2023')
|
||||
cy.get(`[aria-label="Accepted invite"]`)
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<GroupMembers />
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the group members page', function () {
|
||||
cy.get('h1').contains('My Awesome Team')
|
||||
cy.get('small').contains('You have added 2 of 10 available members')
|
||||
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.contains('john.doe@test.com')
|
||||
cy.contains('John Doe')
|
||||
cy.contains('15th Jan 2023')
|
||||
cy.get('.badge-new-comment').contains('Pending invite')
|
||||
})
|
||||
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.contains('Bobby Lapointe')
|
||||
cy.contains('2nd Jan 2023')
|
||||
cy.get('.badge-new-comment').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('sends an invite', function () {
|
||||
cy.intercept('POST', PATHS.addMember, {
|
||||
statusCode: 201,
|
||||
body: {
|
||||
user: {
|
||||
email: 'someone.else@test.com',
|
||||
invite: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
cy.get('.form-control').type('someone.else@test.com')
|
||||
cy.get('.add-more-members-form button').click()
|
||||
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.contains('someone.else@test.com')
|
||||
cy.contains('N/A')
|
||||
cy.get('.badge-new-comment').contains('Pending invite')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('tries to send an invite and displays the error', function () {
|
||||
cy.intercept('POST', PATHS.addMember, {
|
||||
statusCode: 500,
|
||||
body: {
|
||||
error: {
|
||||
message: 'User already added',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
cy.get('.form-control').type('someone.else@test.com')
|
||||
cy.get('.add-more-members-form button').click()
|
||||
cy.get('.alert').contains('Error: User already added')
|
||||
})
|
||||
|
||||
it('checks the select all checkbox', function () {
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('.select-all').click()
|
||||
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.get('.select-item').should('be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.get('.select-item').should('be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('remove a member', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 200,
|
||||
})
|
||||
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.get('.select-item').check()
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
|
||||
cy.get('small').contains('You have added 1 of 10 available members')
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.contains('Bobby Lapointe')
|
||||
cy.contains('2nd Jan 2023')
|
||||
cy.contains('Pending invite').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('tries to remove a user and displays the error', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 500,
|
||||
})
|
||||
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.get('.select-item').check()
|
||||
})
|
||||
})
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
|
||||
cy.get('.alert').contains('Sorry, something went wrong')
|
||||
})
|
||||
})
|
||||
|
||||
it('sends an invite', function () {
|
||||
cy.intercept('POST', PATHS.addMember, {
|
||||
statusCode: 201,
|
||||
body: {
|
||||
user: {
|
||||
email: 'someone.else@test.com',
|
||||
invite: true,
|
||||
describe('with Managed Users enabled', function () {
|
||||
const JOHN_DOE = {
|
||||
_id: 'abc123def456',
|
||||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
email: 'john.doe@test.com',
|
||||
last_active_at: new Date('2023-01-15'),
|
||||
invite: true,
|
||||
}
|
||||
const BOBBY_LAPOINTE = {
|
||||
_id: 'bcd234efa567',
|
||||
first_name: 'Bobby',
|
||||
last_name: 'Lapointe',
|
||||
email: 'bobby.lapointe@test.com',
|
||||
last_active_at: new Date('2023-01-02'),
|
||||
invite: false,
|
||||
}
|
||||
const CLAIRE_JENNINGS = {
|
||||
_id: 'defabc231453',
|
||||
first_name: 'Claire',
|
||||
last_name: 'Jennings',
|
||||
email: 'claire.jennings@test.com',
|
||||
last_active_at: new Date('2023-01-03'),
|
||||
invite: false,
|
||||
enrollment: {
|
||||
managedBy: GROUP_ID,
|
||||
enrolledAt: new Date('2023-01-03'),
|
||||
sso: {
|
||||
providerId: '123',
|
||||
externalId: '123',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache = new Map()
|
||||
win.metaAttributesCache.set('ol-users', [
|
||||
JOHN_DOE,
|
||||
BOBBY_LAPOINTE,
|
||||
CLAIRE_JENNINGS,
|
||||
])
|
||||
win.metaAttributesCache.set('ol-groupId', GROUP_ID)
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Team')
|
||||
win.metaAttributesCache.set('ol-groupSize', 10)
|
||||
win.metaAttributesCache.set('ol-managedUsersActive', true)
|
||||
})
|
||||
mountGroupMembersProvider()
|
||||
})
|
||||
|
||||
cy.get('.form-control').type('someone.else@test.com')
|
||||
cy.get('button').click()
|
||||
it('renders the group members page', function () {
|
||||
cy.get('h1').contains('My Awesome Team')
|
||||
cy.get('small').contains('You have added 3 of 10 available members')
|
||||
|
||||
cy.get('ul').within(() => {
|
||||
cy.get('li:nth-child(4)').within(() => {
|
||||
cy.contains('someone.else@test.com')
|
||||
cy.contains('N/A')
|
||||
cy.get(`[aria-label="Invite not yet accepted"]`)
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.contains('john.doe@test.com')
|
||||
cy.contains('John Doe')
|
||||
cy.contains('15th Jan 2023')
|
||||
cy.get('.sr-only').contains('Pending invite')
|
||||
cy.get('.badge-new-comment').contains('Pending invite')
|
||||
cy.get(`.security-state-invite-pending`).should('exist')
|
||||
|
||||
cy.get('.badge-new-comment').contains('Pending invite')
|
||||
cy.get(`.security-state-invite-pending`).should('exist')
|
||||
})
|
||||
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.contains('Bobby Lapointe')
|
||||
cy.contains('2nd Jan 2023')
|
||||
cy.get('.badge-new-comment').should('not.exist')
|
||||
cy.get('.sr-only').contains('Not managed')
|
||||
})
|
||||
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.contains('claire.jennings@test.com')
|
||||
cy.contains('Claire Jennings')
|
||||
cy.contains('3rd Jan 2023')
|
||||
cy.get('.badge-new-comment').should('not.exist')
|
||||
cy.get('.sr-only').contains('Managed')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('sends an invite', function () {
|
||||
cy.intercept('POST', PATHS.addMember, {
|
||||
statusCode: 201,
|
||||
body: {
|
||||
user: {
|
||||
email: 'someone.else@test.com',
|
||||
invite: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
cy.get('.form-control').type('someone.else@test.com')
|
||||
cy.get('.add-more-members-form button').click()
|
||||
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(4)').within(() => {
|
||||
cy.contains('someone.else@test.com')
|
||||
cy.contains('N/A')
|
||||
cy.get('.sr-only').contains('Pending invite')
|
||||
cy.get('.badge-new-comment').contains('Pending invite')
|
||||
cy.get(`.security-state-invite-pending`).should('exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('tries to send an invite and displays the error', function () {
|
||||
cy.intercept('POST', PATHS.addMember, {
|
||||
statusCode: 500,
|
||||
body: {
|
||||
error: {
|
||||
message: 'User already added',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
cy.get('.form-control').type('someone.else@test.com')
|
||||
cy.get('.add-more-members-form button').click()
|
||||
cy.get('.alert').contains('Error: User already added')
|
||||
})
|
||||
|
||||
it('checks the select all checkbox', function () {
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('.select-all').click()
|
||||
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.get('.select-item').should('be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.get('.select-item').should('be.checked')
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
})
|
||||
|
||||
it('remove a member', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 200,
|
||||
})
|
||||
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.get('.select-item').check()
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
|
||||
cy.get('small').contains('You have added 2 of 10 available members')
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.contains('Bobby Lapointe')
|
||||
cy.contains('2nd Jan 2023')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('cannot remove a managed member', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 200,
|
||||
})
|
||||
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
// no checkbox should be shown for 'Claire Jennings', a managed user
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.get('.select-item').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('tries to remove a user and displays the error', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 500,
|
||||
})
|
||||
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.get('.select-item').check()
|
||||
})
|
||||
})
|
||||
cy.get('.page-header').within(() => {
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
})
|
||||
|
||||
cy.get('.alert').contains('Sorry, something went wrong')
|
||||
})
|
||||
})
|
||||
|
||||
it('tries to send an invite and displays the error', function () {
|
||||
cy.intercept('POST', PATHS.addMember, {
|
||||
statusCode: 500,
|
||||
body: {
|
||||
error: {
|
||||
message: 'User already added',
|
||||
describe('with Group SSO enabled', function () {
|
||||
const JOHN_DOE = {
|
||||
_id: 'abc123def456',
|
||||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
email: 'john.doe@test.com',
|
||||
last_active_at: new Date('2023-01-15'),
|
||||
invite: true,
|
||||
}
|
||||
const BOBBY_LAPOINTE = {
|
||||
_id: 'bcd234efa567',
|
||||
first_name: 'Bobby',
|
||||
last_name: 'Lapointe',
|
||||
email: 'bobby.lapointe@test.com',
|
||||
last_active_at: new Date('2023-01-02'),
|
||||
invite: false,
|
||||
}
|
||||
const CLAIRE_JENNINGS = {
|
||||
_id: 'defabc231453',
|
||||
first_name: 'Claire',
|
||||
last_name: 'Jennings',
|
||||
email: 'claire.jennings@test.com',
|
||||
last_active_at: new Date('2023-01-03'),
|
||||
invite: false,
|
||||
enrollment: {
|
||||
managedBy: GROUP_ID,
|
||||
enrolledAt: new Date('2023-01-03'),
|
||||
sso: {
|
||||
providerId: '123',
|
||||
externalId: '123',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache = new Map()
|
||||
win.metaAttributesCache.set('ol-users', [
|
||||
JOHN_DOE,
|
||||
BOBBY_LAPOINTE,
|
||||
CLAIRE_JENNINGS,
|
||||
])
|
||||
win.metaAttributesCache.set('ol-groupId', GROUP_ID)
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Team')
|
||||
win.metaAttributesCache.set('ol-groupSize', 10)
|
||||
win.metaAttributesCache.set('ol-managedUsersActive', false)
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', true)
|
||||
})
|
||||
|
||||
mountGroupMembersProvider()
|
||||
})
|
||||
|
||||
cy.get('.form-control').type('someone.else@test.com')
|
||||
cy.get('button').click()
|
||||
cy.get('.alert').contains('Error: User already added')
|
||||
})
|
||||
it('should display the Security column', function () {
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.get('.sr-only').contains('SSO not active')
|
||||
})
|
||||
|
||||
it('checks the select all checkbox', function () {
|
||||
cy.get('ul').within(() => {
|
||||
cy.get('li:nth-child(2)').within(() => {
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
})
|
||||
cy.get('li:nth-child(3)').within(() => {
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.contains('claire.jennings@test.com')
|
||||
cy.get('.sr-only').contains('SSO active')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('.select-all').click()
|
||||
|
||||
cy.get('ul').within(() => {
|
||||
cy.get('li:nth-child(2)').within(() => {
|
||||
cy.get('.select-item').should('be.checked')
|
||||
})
|
||||
cy.get('li:nth-child(3)').within(() => {
|
||||
cy.get('.select-item').should('be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('remove a member', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 200,
|
||||
})
|
||||
|
||||
cy.get('ul').within(() => {
|
||||
cy.get('li:nth-child(2)').within(() => {
|
||||
cy.get('.select-item').check()
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
|
||||
cy.get('small').contains('You have added 1 of 10 available members')
|
||||
cy.get('ul').within(() => {
|
||||
cy.get('li:nth-child(2)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.contains('Bobby Lapointe')
|
||||
cy.contains('2nd Jan 2023')
|
||||
cy.get(`[aria-label="Accepted invite"]`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('tries to remove a user and displays the error', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 500,
|
||||
})
|
||||
|
||||
cy.get('ul').within(() => {
|
||||
cy.get('li:nth-child(2)').within(() => {
|
||||
cy.get('.select-item').check()
|
||||
})
|
||||
})
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
|
||||
cy.get('.alert').contains('Sorry, something went wrong')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import InstitutionManagers from '../../../../../frontend/js/features/group-management/components/institution-managers'
|
||||
import InstitutionManagers from '@/features/group-management/components/institution-managers'
|
||||
|
||||
const JOHN_DOE = {
|
||||
_id: 'abc123def456',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import GroupMembers from '../../../../../../frontend/js/features/group-management/components/group-members'
|
||||
import { GroupMembersProvider } from '../../../../../../frontend/js/features/group-management/context/group-members-context'
|
||||
import GroupMembers from '@/features/group-management/components/group-members'
|
||||
import { GroupMembersProvider } from '@/features/group-management/context/group-members-context'
|
||||
|
||||
const GROUP_ID = '777fff777fff'
|
||||
const JOHN_DOE = {
|
||||
@@ -241,16 +241,17 @@ describe('Group members when group SSO is enabled', function () {
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.get('.sr-only').contains('SSO unlinked').should('not.exist')
|
||||
cy.get('.sr-only').contains('SSO not active').should('not.exist')
|
||||
})
|
||||
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.contains('claire.jennings@test.com')
|
||||
cy.get('.sr-only').contains('SSO linked').should('not.exist')
|
||||
cy.get('.sr-only').contains('SSO active').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
it('should display SSO Column when group sso is not enabled', function () {
|
||||
|
||||
it('should display SSO Column when Group SSO is enabled', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', true)
|
||||
})
|
||||
@@ -258,12 +259,12 @@ describe('Group members when group SSO is enabled', function () {
|
||||
cy.get('ul.managed-users-list table > tbody').within(() => {
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.get('.sr-only').contains('SSO unlinked')
|
||||
cy.get('.sr-only').contains('SSO not active')
|
||||
})
|
||||
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.contains('claire.jennings@test.com')
|
||||
cy.get('.sr-only').contains('SSO linked')
|
||||
cy.get('.sr-only').contains('SSO active')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,167 +0,0 @@
|
||||
import sinon from 'sinon'
|
||||
import ManagedUserRow from '../../../../../../frontend/js/features/group-management/components/managed-users/managed-user-row'
|
||||
import { GroupMembersProvider } from '../../../../../../frontend/js/features/group-management/context/group-members-context'
|
||||
import { User } from '../../../../../../types/group-management/user'
|
||||
|
||||
describe('ManagedUserRow', function () {
|
||||
const subscriptionId = '123abc'
|
||||
|
||||
describe('with an ordinary user', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<ManagedUserRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the row', function () {
|
||||
cy.get('tr').should('exist')
|
||||
// Checkbox
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
// Email
|
||||
cy.get('tr').contains(user.email)
|
||||
// Name
|
||||
cy.get('tr').contains(user.first_name)
|
||||
cy.get('tr').contains(user.last_name)
|
||||
// Last active date
|
||||
cy.get('tr').contains('21st Nov 2070')
|
||||
// Managed status
|
||||
cy.get('tr').contains('Managed')
|
||||
// Dropdown button
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a pending invite', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: true,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<ManagedUserRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Pending invite" badge', function () {
|
||||
cy.get('.badge-new-comment').contains('Pending invite')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a group admin', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<ManagedUserRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Group admin" symbol', function () {
|
||||
cy.get('[aria-label="Group admin"].fa-user-circle-o').should('exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('selecting and unselecting user row', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<ManagedUserRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should select and unselect the user', function () {
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
cy.get('.select-item').click()
|
||||
cy.get('.select-item').should('be.checked')
|
||||
cy.get('.select-item').click()
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { PropsWithChildren } from 'react'
|
||||
import sinon from 'sinon'
|
||||
import ManagedUserDropdownButton from '../../../../../../frontend/js/features/group-management/components/managed-users/managed-user-dropdown-button'
|
||||
import { GroupMembersProvider } from '../../../../../../frontend/js/features/group-management/context/group-members-context'
|
||||
import DropdownButton from '@/features/group-management/components/members-table/dropdown-button'
|
||||
import { GroupMembersProvider } from '@/features/group-management/context/group-members-context'
|
||||
import { User } from '../../../../../../types/group-management/user'
|
||||
|
||||
function Wrapper({ children }: PropsWithChildren<Record<string, unknown>>) {
|
||||
@@ -20,7 +20,7 @@ function Wrapper({ children }: PropsWithChildren<Record<string, unknown>>) {
|
||||
function mountDropDownComponent(user: User, subscriptionId: string) {
|
||||
cy.mount(
|
||||
<Wrapper>
|
||||
<ManagedUserDropdownButton
|
||||
<DropdownButton
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
@@ -218,6 +218,7 @@ describe('ManagedUserDropdownButton', function () {
|
||||
cy.findByTestId('no-actions-available').should('exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('sending SSO invite reminder', function () {
|
||||
const user = {
|
||||
_id: 'some-user',
|
||||
@@ -1,7 +1,7 @@
|
||||
import ManagedUserStatus from '../../../../../../frontend/js/features/group-management/components/managed-users/managed-user-status'
|
||||
import ManagedUserStatus from '@/features/group-management/components/members-table/managed-user-status'
|
||||
import { User } from '../../../../../../types/group-management/user'
|
||||
|
||||
describe('ManagedUserStatus', function () {
|
||||
describe('MemberStatus', function () {
|
||||
describe('with a pending invite', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
@@ -0,0 +1,685 @@
|
||||
import sinon from 'sinon'
|
||||
import MemberRow from '@/features/group-management/components/members-table/member-row'
|
||||
import { GroupMembersProvider } from '@/features/group-management/context/group-members-context'
|
||||
import { User } from '../../../../../../types/group-management/user'
|
||||
|
||||
describe('MemberRow', function () {
|
||||
const subscriptionId = '123abc'
|
||||
|
||||
describe('default view', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache = new Map()
|
||||
})
|
||||
})
|
||||
|
||||
describe('with an ordinary user', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the row', function () {
|
||||
cy.get('tr').should('exist')
|
||||
// Checkbox
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
// Email
|
||||
cy.get('tr').contains(user.email)
|
||||
// Name
|
||||
cy.get('tr').contains(user.first_name)
|
||||
cy.get('tr').contains(user.last_name)
|
||||
// Last active date
|
||||
cy.get('tr').contains('21st Nov 2070')
|
||||
// Dropdown button
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
|
||||
cy.get('tr').contains('SSO').should('not.exist')
|
||||
cy.get('tr').contains('Managed').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a pending invite', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: true,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Pending invite" badge', function () {
|
||||
cy.get('.badge-new-comment').contains('Pending invite')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a group admin', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Group admin" symbol', function () {
|
||||
cy.get('[aria-label="Group admin"].fa-user-circle-o').should('exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('selecting and unselecting user row', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should select and unselect the user', function () {
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
cy.get('.select-item').click()
|
||||
cy.get('.select-item').should('be.checked')
|
||||
cy.get('.select-item').click()
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Managed Users enabled', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache = new Map()
|
||||
win.metaAttributesCache.set('ol-managedUsersActive', true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with an ordinary user', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the row', function () {
|
||||
cy.get('tr').should('exist')
|
||||
// Checkbox
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
// Email
|
||||
cy.get('tr').contains(user.email)
|
||||
// Name
|
||||
cy.get('tr').contains(user.first_name)
|
||||
cy.get('tr').contains(user.last_name)
|
||||
// Last active date
|
||||
cy.get('tr').contains('21st Nov 2070')
|
||||
// Managed status
|
||||
cy.get('tr').contains('Managed')
|
||||
// Dropdown button
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a pending invite', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: true,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Pending invite" badge', function () {
|
||||
cy.get('.badge-new-comment').contains('Pending invite')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a group admin', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Group admin" symbol', function () {
|
||||
cy.get('[aria-label="Group admin"].fa-user-circle-o').should('exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('selecting and unselecting user row', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should select and unselect the user', function () {
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
cy.get('.select-item').click()
|
||||
cy.get('.select-item').should('be.checked')
|
||||
cy.get('.select-item').click()
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Group SSO enabled', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache = new Map()
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with an ordinary user', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the row', function () {
|
||||
cy.get('tr').should('exist')
|
||||
// Checkbox
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
// Email
|
||||
cy.get('tr').contains(user.email)
|
||||
// Name
|
||||
cy.get('tr').contains(user.first_name)
|
||||
cy.get('tr').contains(user.last_name)
|
||||
// Last active date
|
||||
cy.get('tr').contains('21st Nov 2070')
|
||||
// SSO status
|
||||
cy.get('tr').contains('SSO')
|
||||
// Dropdown button
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
|
||||
cy.get('tr').contains('Managed').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a pending invite', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: true,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Pending invite" badge', function () {
|
||||
cy.get('.badge-new-comment').contains('Pending invite')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a group admin', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Group admin" symbol', function () {
|
||||
cy.get('[aria-label="Group admin"].fa-user-circle-o').should('exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('selecting and unselecting user row', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should select and unselect the user', function () {
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
cy.get('.select-item').click()
|
||||
cy.get('.select-item').should('be.checked')
|
||||
cy.get('.select-item').click()
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Managed Users and Group SSO enabled', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache = new Map()
|
||||
win.metaAttributesCache.set('ol-managedUsersActive', true)
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with an ordinary user', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the row', function () {
|
||||
cy.get('tr').should('exist')
|
||||
// Checkbox
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
// Email
|
||||
cy.get('tr').contains(user.email)
|
||||
// Name
|
||||
cy.get('tr').contains(user.first_name)
|
||||
cy.get('tr').contains(user.last_name)
|
||||
// Last active date
|
||||
cy.get('tr').contains('21st Nov 2070')
|
||||
// Managed status
|
||||
cy.get('tr').contains('Managed')
|
||||
// SSO status
|
||||
cy.get('tr').contains('SSO')
|
||||
// Dropdown button
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a pending invite', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: true,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Pending invite" badge', function () {
|
||||
cy.get('.badge-new-comment').contains('Pending invite')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a group admin', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Group admin" symbol', function () {
|
||||
cy.get('[aria-label="Group admin"].fa-user-circle-o').should('exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('selecting and unselecting user row', function () {
|
||||
let user: User
|
||||
|
||||
beforeEach(function () {
|
||||
user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-11-21T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MemberRow
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setManagedUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should select and unselect the user', function () {
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
cy.get('.select-item').click()
|
||||
cy.get('.select-item').should('be.checked')
|
||||
cy.get('.select-item').click()
|
||||
cy.get('.select-item').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,17 +1,17 @@
|
||||
import ManagedUsersList from '../../../../../../frontend/js/features/group-management/components/managed-users/managed-users-list'
|
||||
import { GroupMembersProvider } from '../../../../../../frontend/js/features/group-management/context/group-members-context'
|
||||
import MembersList from '@/features/group-management/components/members-table/members-list'
|
||||
import { GroupMembersProvider } from '@/features/group-management/context/group-members-context'
|
||||
|
||||
const groupId = 'somegroup'
|
||||
|
||||
function mountManagedUsersList() {
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<ManagedUsersList groupId={groupId} />
|
||||
<MembersList groupId={groupId} />
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
}
|
||||
|
||||
describe('ManagedUsersList', function () {
|
||||
describe('MembersList', function () {
|
||||
describe('with users', function () {
|
||||
const users = [
|
||||
{
|
||||
@@ -98,7 +98,7 @@ describe('ManagedUsersList', function () {
|
||||
})
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<ManagedUsersList groupId={groupId} />
|
||||
<MembersList groupId={groupId} />
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
import OffboardManagedUserModal from '../../../../../../frontend/js/features/group-management/components/managed-users/offboard-managed-user-modal'
|
||||
import OffboardManagedUserModal from '@/features/group-management/components/members-table/offboard-managed-user-modal'
|
||||
import sinon from 'sinon'
|
||||
|
||||
describe('OffboardManagedUserModal', function () {
|
||||
@@ -1,4 +1,4 @@
|
||||
import PublisherManagers from '../../../../../frontend/js/features/group-management/components/publisher-managers'
|
||||
import PublisherManagers from '@/features/group-management/components/publisher-managers'
|
||||
|
||||
const JOHN_DOE = {
|
||||
_id: 'abc123def456',
|
||||
|
||||
Reference in New Issue
Block a user