first commit
This commit is contained in:
@@ -0,0 +1,374 @@
|
||||
import AddSeats, {
|
||||
MAX_NUMBER_OF_USERS,
|
||||
} from '@/features/group-management/components/add-seats/add-seats'
|
||||
|
||||
describe('<AddSeats />', function () {
|
||||
beforeEach(function () {
|
||||
this.totalLicenses = 5
|
||||
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Team')
|
||||
win.metaAttributesCache.set('ol-subscriptionId', '123')
|
||||
win.metaAttributesCache.set('ol-totalLicenses', this.totalLicenses)
|
||||
win.metaAttributesCache.set('ol-isProfessional', false)
|
||||
})
|
||||
|
||||
cy.mount(<AddSeats />)
|
||||
|
||||
cy.findByRole('button', { name: /buy licenses/i })
|
||||
cy.findByTestId('add-more-users-group-form')
|
||||
})
|
||||
|
||||
it('renders the back button', function () {
|
||||
cy.findByTestId('group-heading').within(() => {
|
||||
cy.findByRole('button', { name: /back to subscription/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/user/subscription'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('shows the group name', function () {
|
||||
cy.findByTestId('group-heading').within(() => {
|
||||
cy.findByRole('heading', { name: 'My Awesome Team' })
|
||||
})
|
||||
})
|
||||
|
||||
it('shows the "Buy more licenses" label', function () {
|
||||
cy.findByText(/buy more licenses/i)
|
||||
})
|
||||
|
||||
it('shows the maximum supported users', function () {
|
||||
cy.findByText(
|
||||
new RegExp(
|
||||
`your current plan supports up to ${this.totalLicenses} licenses`,
|
||||
'i'
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
it('shows instructions on how to reduce licenses on a plan', function () {
|
||||
cy.contains(
|
||||
/if you want to reduce the number of licenses on your plan, please contact customer support/i
|
||||
).within(() => {
|
||||
cy.findByRole('link', { name: /contact customer support/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/contact'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('renders the cancel button', function () {
|
||||
cy.findByRole('button', { name: /cancel/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/user/subscription'
|
||||
)
|
||||
})
|
||||
|
||||
describe('"Upgrade my plan" link', function () {
|
||||
it('shows the link', function () {
|
||||
cy.findByRole('link', { name: /upgrade my plan/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/user/subscription/group/upgrade-subscription'
|
||||
)
|
||||
})
|
||||
|
||||
it('hides the link', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-isProfessional', true)
|
||||
})
|
||||
|
||||
cy.mount(<AddSeats />)
|
||||
|
||||
cy.findByRole('link', { name: /upgrade my plan/i }).should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('cost summary', function () {
|
||||
beforeEach(function () {
|
||||
cy.findByLabelText(/how many licenses do you want to buy/i).as('input')
|
||||
})
|
||||
|
||||
it('shows the title', function () {
|
||||
cy.findByTestId('cost-summary').within(() => {
|
||||
cy.findByText(/cost summary/i)
|
||||
})
|
||||
})
|
||||
|
||||
describe('shows default content when', function () {
|
||||
afterEach(function () {
|
||||
cy.findByTestId('cost-summary').within(() => {
|
||||
cy.findByText(
|
||||
/enter the number of licenses you’d like to add to see the cost breakdown/i
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('leaves input empty', function () {
|
||||
cy.get('@input').should('have.value', '')
|
||||
})
|
||||
|
||||
it('fills in a non-numeric value', function () {
|
||||
cy.get('@input').type('ab')
|
||||
cy.findByText(/value must be a number/i)
|
||||
})
|
||||
|
||||
it('fills in a decimal value', function () {
|
||||
cy.get('@input').type('1.5')
|
||||
cy.findByText(/value must be a whole number/i)
|
||||
})
|
||||
|
||||
it('fills in a "0" value', function () {
|
||||
cy.get('@input').type('0')
|
||||
cy.findByText(/value must be at least 1/i)
|
||||
})
|
||||
|
||||
it('fills in a value and clears the input', function () {
|
||||
cy.get('@input').type('a{backspace}')
|
||||
cy.get('@input').should('have.text', '')
|
||||
cy.findByText(/this field is required/i)
|
||||
})
|
||||
})
|
||||
|
||||
describe('entered more than the maximum allowed number of users', function () {
|
||||
beforeEach(function () {
|
||||
this.numberOfUsersExceedingMaxLimit = MAX_NUMBER_OF_USERS + 1
|
||||
|
||||
cy.get('@input').type(this.numberOfUsersExceedingMaxLimit.toString())
|
||||
cy.findByRole('button', { name: /buy licenses/i }).should('not.exist')
|
||||
cy.findByRole('button', { name: /send request/i }).as('sendRequestBtn')
|
||||
})
|
||||
|
||||
it('renders a notification', function () {
|
||||
cy.findByTestId('cost-summary').should('not.exist')
|
||||
cy.findByRole('alert').should(
|
||||
'contain.text',
|
||||
`If you want more than ${MAX_NUMBER_OF_USERS} licenses on your plan, we need to add them for you. Just click Send request below and we’ll be happy to help.`
|
||||
)
|
||||
})
|
||||
|
||||
describe('request', function () {
|
||||
afterEach(function () {
|
||||
cy.findByRole('button', { name: /go to subscriptions/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/user/subscription'
|
||||
)
|
||||
})
|
||||
|
||||
function makeRequest(statusCode: number, adding: string) {
|
||||
cy.intercept(
|
||||
'POST',
|
||||
'/user/subscription/group/add-users/sales-contact-form',
|
||||
{
|
||||
statusCode,
|
||||
}
|
||||
).as('addUsersRequest')
|
||||
cy.get('@sendRequestBtn').click()
|
||||
cy.get('@addUsersRequest').its('request.body').should('deep.equal', {
|
||||
adding,
|
||||
})
|
||||
cy.findByTestId('add-more-users-group-form').should('not.exist')
|
||||
}
|
||||
|
||||
it('sends a request that succeeds', function () {
|
||||
makeRequest(204, this.numberOfUsersExceedingMaxLimit.toString())
|
||||
cy.findByTestId('title').should(
|
||||
'contain.text',
|
||||
'We’ve got your request'
|
||||
)
|
||||
cy.findByText(/our team will get back to you shortly/i)
|
||||
})
|
||||
|
||||
it('sends a request that fails', function () {
|
||||
makeRequest(400, this.numberOfUsersExceedingMaxLimit.toString())
|
||||
cy.findByTestId('title').should(
|
||||
'contain.text',
|
||||
'Something went wrong'
|
||||
)
|
||||
cy.contains(
|
||||
/it looks like that didn’t work. You can try again or get in touch with our Support team for more help/i
|
||||
).within(() => {
|
||||
cy.findByRole('link', { name: /get in touch/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/contact'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('entered less than the maximum allowed number of users', function () {
|
||||
beforeEach(function () {
|
||||
this.adding = 1
|
||||
this.body = {
|
||||
change: {
|
||||
type: 'add-on-update',
|
||||
addOn: {
|
||||
code: 'additional-license',
|
||||
quantity: this.totalLicenses + this.adding,
|
||||
prevQuantity: this.totalLicenses,
|
||||
},
|
||||
},
|
||||
currency: 'USD',
|
||||
immediateCharge: {
|
||||
subtotal: 100,
|
||||
tax: 20,
|
||||
total: 120,
|
||||
discount: 0,
|
||||
},
|
||||
nextInvoice: {
|
||||
date: '2025-12-01T00:00:00.000Z',
|
||||
plan: {
|
||||
name: 'Overleaf Standard Group',
|
||||
amount: 0,
|
||||
},
|
||||
subtotal: 895,
|
||||
tax: {
|
||||
rate: 0.2,
|
||||
amount: 105,
|
||||
},
|
||||
total: 1000,
|
||||
},
|
||||
}
|
||||
|
||||
cy.findByRole('button', { name: /buy licenses/i }).as('addUsersBtn')
|
||||
cy.findByRole('button', { name: /send request/i }).should('not.exist')
|
||||
})
|
||||
|
||||
it('renders the preview data', function () {
|
||||
cy.intercept('POST', '/user/subscription/group/add-users/preview', {
|
||||
statusCode: 200,
|
||||
body: this.body,
|
||||
}).as('addUsersRequest')
|
||||
cy.get('@input').type(this.adding.toString())
|
||||
|
||||
cy.findByTestId('cost-summary').within(() => {
|
||||
cy.contains(
|
||||
new RegExp(
|
||||
`you’re adding ${this.adding} licenses to your plan giving you a total of ${this.body.change.addOn.quantity} licenses`,
|
||||
'i'
|
||||
)
|
||||
)
|
||||
|
||||
cy.findByTestId('plan').within(() => {
|
||||
cy.findByText(
|
||||
`${this.body.nextInvoice.plan.name} x ${this.adding} Licenses`
|
||||
)
|
||||
cy.findByTestId('price').should(
|
||||
'have.text',
|
||||
`$${this.body.immediateCharge.subtotal}.00`
|
||||
)
|
||||
})
|
||||
|
||||
cy.findByTestId('tax').within(() => {
|
||||
cy.findByText(
|
||||
new RegExp(`VAT · ${this.body.nextInvoice.tax.rate * 100}%`, 'i')
|
||||
)
|
||||
cy.findByTestId('price').should(
|
||||
'have.text',
|
||||
`$${this.body.immediateCharge.tax}.00`
|
||||
)
|
||||
})
|
||||
|
||||
cy.findByTestId('discount').should('not.exist')
|
||||
|
||||
cy.findByTestId('total').within(() => {
|
||||
cy.findByText(/total due today/i)
|
||||
cy.findByTestId('price').should(
|
||||
'have.text',
|
||||
`$${this.body.immediateCharge.total}.00`
|
||||
)
|
||||
})
|
||||
|
||||
cy.findByText(
|
||||
/we’ll charge you now for the cost of your additional licenses based on the remaining months of your current subscription/i
|
||||
)
|
||||
cy.findByText(
|
||||
/after that, we’ll bill you \$1,000\.00 \(\$895\.00 \+ \$105\.00 tax\) annually on December 1, unless you cancel/i
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('renders the preview data with discount', function () {
|
||||
this.body.immediateCharge.discount = 50
|
||||
|
||||
cy.intercept('POST', '/user/subscription/group/add-users/preview', {
|
||||
statusCode: 200,
|
||||
body: this.body,
|
||||
}).as('addUsersRequest')
|
||||
cy.get('@input').type(this.adding.toString())
|
||||
|
||||
cy.findByTestId('cost-summary').within(() => {
|
||||
cy.findByTestId('discount').within(() => {
|
||||
cy.findByText(`($${this.body.immediateCharge.discount}.00)`)
|
||||
})
|
||||
|
||||
cy.findByText(
|
||||
/This does not include your current discounts, which will be applied automatically before your next payment/i
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('request', function () {
|
||||
afterEach(function () {
|
||||
cy.findByRole('button', { name: /go to subscriptions/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/user/subscription'
|
||||
)
|
||||
})
|
||||
|
||||
function makeRequest(statusCode: number, adding: string) {
|
||||
cy.intercept('POST', '/user/subscription/group/add-users/create', {
|
||||
statusCode,
|
||||
}).as('addUsersRequest')
|
||||
cy.get('@input').type(adding)
|
||||
cy.get('@addUsersBtn').click()
|
||||
cy.get('@addUsersRequest')
|
||||
.its('request.body')
|
||||
.should('deep.equal', {
|
||||
adding: Number(adding),
|
||||
})
|
||||
cy.findByTestId('add-more-users-group-form').should('not.exist')
|
||||
}
|
||||
|
||||
it('sends a request that succeeds', function () {
|
||||
makeRequest(204, this.adding.toString())
|
||||
cy.findByTestId('title').should(
|
||||
'contain.text',
|
||||
'You’ve added more license(s)'
|
||||
)
|
||||
cy.findByText(/you’ve added more license\(s\) to your subscription/i)
|
||||
cy.findByRole('link', { name: /invite people/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/manage/groups/123/members'
|
||||
)
|
||||
})
|
||||
|
||||
it('sends a request that fails', function () {
|
||||
makeRequest(400, this.adding.toString())
|
||||
cy.findByTestId('title').should(
|
||||
'contain.text',
|
||||
'Something went wrong'
|
||||
)
|
||||
cy.contains(
|
||||
/it looks like that didn’t work. You can try again or get in touch with our Support team for more help/i
|
||||
).within(() => {
|
||||
cy.findByRole('link', { name: /get in touch/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/contact'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,175 @@
|
||||
import GroupManagers from '@/features/group-management/components/group-managers'
|
||||
|
||||
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 = '888fff888fff'
|
||||
const PATHS = {
|
||||
addMember: `/manage/groups/${GROUP_ID}/managers`,
|
||||
removeMember: `/manage/groups/${GROUP_ID}/managers`,
|
||||
}
|
||||
|
||||
describe('group managers', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [JOHN_DOE, BOBBY_LAPOINTE])
|
||||
win.metaAttributesCache.set('ol-groupId', GROUP_ID)
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Team')
|
||||
})
|
||||
|
||||
cy.mount(<GroupManagers />)
|
||||
})
|
||||
|
||||
it('renders the group management page', function () {
|
||||
cy.findByRole('heading', { name: /my awesome team/i, level: 1 })
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByText('john.doe@test.com')
|
||||
cy.findByText('John Doe')
|
||||
cy.findByText('15th Jan 2023')
|
||||
cy.findByText('Invite not yet accepted')
|
||||
})
|
||||
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByText('bobby.lapointe@test.com')
|
||||
cy.findByText('Bobby Lapointe')
|
||||
cy.findByText('2nd Jan 2023')
|
||||
cy.findByText('Accepted invite')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('sends an invite', function () {
|
||||
cy.intercept('POST', PATHS.addMember, {
|
||||
statusCode: 201,
|
||||
body: {
|
||||
user: {
|
||||
email: 'someone.else@test.com',
|
||||
invite: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
cy.findByTestId('add-members-form').within(() => {
|
||||
cy.findByRole('textbox').type('someone.else@test.com')
|
||||
cy.findByRole('button').click()
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.findByText('someone.else@test.com')
|
||||
cy.findByText('N/A')
|
||||
cy.findByText('Invite not yet accepted')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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.findByTestId('add-members-form').within(() => {
|
||||
cy.findByRole('textbox').type('someone.else@test.com')
|
||||
cy.findByRole('button').click()
|
||||
})
|
||||
cy.findByRole('alert').should('contain.text', 'Error: User already added')
|
||||
})
|
||||
|
||||
it('checks the select all checkbox', function () {
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('not.be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('not.be.checked')
|
||||
})
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('thead')
|
||||
.within(() => {
|
||||
cy.findByLabelText(/select all/i).check()
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('remove a member', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 200,
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).check()
|
||||
})
|
||||
})
|
||||
|
||||
cy.findByRole('button', { name: /remove manager/i }).click()
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByText('bobby.lapointe@test.com')
|
||||
cy.findByText('Bobby Lapointe')
|
||||
cy.findByText('2nd Jan 2023')
|
||||
cy.findByText('Accepted invite')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('tries to remove a manager and displays the error', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 500,
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).check()
|
||||
})
|
||||
})
|
||||
cy.findByRole('button', { name: /remove manager/i }).click()
|
||||
|
||||
cy.findByRole('alert').should('contain.text', 'Sorry, something went wrong')
|
||||
})
|
||||
})
|
@@ -0,0 +1,577 @@
|
||||
import GroupMembers from '@/features/group-management/components/group-members'
|
||||
import { GroupMembersProvider } from '@/features/group-management/context/group-members-context'
|
||||
import { User } from '../../../../../types/group-management/user'
|
||||
|
||||
const GROUP_ID = '777fff777fff'
|
||||
const PATHS = {
|
||||
addMember: `/manage/groups/${GROUP_ID}/invites`,
|
||||
removeMember: `/manage/groups/${GROUP_ID}/user`,
|
||||
removeInvite: `/manage/groups/${GROUP_ID}/invites`,
|
||||
exportMembers: `/manage/groups/${GROUP_ID}/members/export`,
|
||||
}
|
||||
|
||||
describe('GroupMembers', function () {
|
||||
function mountGroupMembersProvider() {
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<GroupMembers />
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
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.mount(
|
||||
<GroupMembersProvider>
|
||||
<GroupMembers />
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the group members page', function () {
|
||||
cy.findByRole('heading', { name: /my awesome team/i, level: 1 })
|
||||
cy.findByTestId('page-header-members-details').contains(
|
||||
'You have added 2 of 10 available members'
|
||||
)
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('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.findByTestId('badge-pending-invite').should(
|
||||
'have.text',
|
||||
'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.findByTestId('badge-pending-invite').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.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.contains('someone.else@test.com')
|
||||
cy.contains('N/A')
|
||||
cy.findByTestId('badge-pending-invite').should(
|
||||
'have.text',
|
||||
'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.findByRole('alert').contains('Error: User already added')
|
||||
})
|
||||
|
||||
it('checks the select all checkbox', function () {
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
|
||||
cy.findByTestId('select-all-checkbox').click()
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('remove a member', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 200,
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').check()
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
|
||||
cy.get('small').contains('You have added 1 of 10 available members')
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('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.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').check()
|
||||
})
|
||||
})
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
|
||||
cy.findByRole('alert').contains('Sorry, something went wrong')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Managed Users enabled', function () {
|
||||
const JOHN_DOE: User = {
|
||||
_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: User = {
|
||||
_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: User = {
|
||||
_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: [
|
||||
{
|
||||
groupId: GROUP_ID,
|
||||
linkedAt: new Date(),
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
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()
|
||||
})
|
||||
|
||||
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.findByTestId('managed-entities-table')
|
||||
.find('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('.visually-hidden').contains('Pending invite')
|
||||
cy.findByTestId('badge-pending-invite').should(
|
||||
'have.text',
|
||||
'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.findByTestId('badge-pending-invite').should('not.exist')
|
||||
cy.get('.visually-hidden').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.findByTestId('badge-pending-invite').should('not.exist')
|
||||
cy.get('.visually-hidden').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.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(4)').within(() => {
|
||||
cy.contains('someone.else@test.com')
|
||||
cy.contains('N/A')
|
||||
cy.get('.visually-hidden').contains('Pending invite')
|
||||
cy.findByTestId('badge-pending-invite').should(
|
||||
'have.text',
|
||||
'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.findByRole('alert').contains('Error: User already added')
|
||||
})
|
||||
|
||||
it('checks the select all checkbox', function () {
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
|
||||
cy.findByTestId('select-all-checkbox').click()
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').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.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').check()
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
|
||||
cy.get('small').contains('You have added 2 of 10 available members')
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('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.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
// no checkbox should be shown for 'Claire Jennings', a managed user
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('tries to remove a user and displays the error', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 500,
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').check()
|
||||
})
|
||||
})
|
||||
cy.get('.page-header').within(() => {
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
})
|
||||
|
||||
cy.findByRole('alert').contains('Sorry, something went wrong')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Group SSO enabled', function () {
|
||||
const JOHN_DOE: User = {
|
||||
_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: User = {
|
||||
_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: User = {
|
||||
_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: [
|
||||
{
|
||||
groupId: GROUP_ID,
|
||||
linkedAt: new Date(),
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
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()
|
||||
})
|
||||
|
||||
it('should display the Security column', function () {
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.get('.visually-hidden').contains('SSO not active')
|
||||
})
|
||||
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.contains('claire.jennings@test.com')
|
||||
cy.get('.visually-hidden').contains('SSO active')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with flexible group licensing enabled', function () {
|
||||
beforeEach(function () {
|
||||
this.JOHN_DOE = {
|
||||
_id: 'abc123def456',
|
||||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
email: 'john.doe@test.com',
|
||||
last_active_at: new Date('2023-01-15'),
|
||||
invite: false,
|
||||
}
|
||||
this.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.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-canUseFlexibleLicensing', true)
|
||||
win.metaAttributesCache.set('ol-canUseAddSeatsFeature', true)
|
||||
})
|
||||
})
|
||||
|
||||
it('renders the group members page with the new text', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [
|
||||
this.JOHN_DOE,
|
||||
this.BOBBY_LAPOINTE,
|
||||
])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<GroupMembers />
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
|
||||
cy.findByTestId('group-size-details').contains(
|
||||
'You have 2 licenses and your plan supports up to 10. Buy more licenses.'
|
||||
)
|
||||
cy.findByTestId('add-more-members-form').within(() => {
|
||||
cy.contains('Invite more members')
|
||||
cy.get('button').contains('Invite')
|
||||
})
|
||||
})
|
||||
|
||||
it('renders the group members page with new text when only has one group member', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [this.JOHN_DOE])
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<GroupMembers />
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
|
||||
cy.findByTestId('group-size-details').contains(
|
||||
'You have 1 license and your plan supports up to 10. Buy more licenses.'
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the group members page without "buy more licenses" link when not admin', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [this.JOHN_DOE])
|
||||
win.metaAttributesCache.set('ol-canUseAddSeatsFeature', false)
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<GroupMembers />
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
|
||||
cy.findByTestId('group-size-details').within(() => {
|
||||
cy.findByText(/you have \d+ license and your plan supports up to \d+/i)
|
||||
cy.findByText(/buy more licenses/i).should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,175 @@
|
||||
import InstitutionManagers from '@/features/group-management/components/institution-managers'
|
||||
|
||||
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 = '999fff999fff'
|
||||
const PATHS = {
|
||||
addMember: `/manage/institutions/${GROUP_ID}/managers`,
|
||||
removeMember: `/manage/institutions/${GROUP_ID}/managers`,
|
||||
}
|
||||
|
||||
describe('institution managers', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [JOHN_DOE, BOBBY_LAPOINTE])
|
||||
win.metaAttributesCache.set('ol-groupId', GROUP_ID)
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Institution')
|
||||
})
|
||||
|
||||
cy.mount(<InstitutionManagers />)
|
||||
})
|
||||
|
||||
it('renders the institution management page', function () {
|
||||
cy.findByRole('heading', { name: /my awesome institution/i, level: 1 })
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByText('john.doe@test.com')
|
||||
cy.findByText('John Doe')
|
||||
cy.findByText('15th Jan 2023')
|
||||
cy.findByText('Invite not yet accepted')
|
||||
})
|
||||
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByText('bobby.lapointe@test.com')
|
||||
cy.findByText('Bobby Lapointe')
|
||||
cy.findByText('2nd Jan 2023')
|
||||
cy.findByText('Accepted invite')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('sends an invite', function () {
|
||||
cy.intercept('POST', PATHS.addMember, {
|
||||
statusCode: 201,
|
||||
body: {
|
||||
user: {
|
||||
email: 'someone.else@test.com',
|
||||
invite: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
cy.findByTestId('add-members-form').within(() => {
|
||||
cy.findByRole('textbox').type('someone.else@test.com')
|
||||
cy.findByRole('button').click()
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.findByText('someone.else@test.com')
|
||||
cy.findByText('N/A')
|
||||
cy.findByText('Invite not yet accepted')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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.findByTestId('add-members-form').within(() => {
|
||||
cy.findByRole('textbox').type('someone.else@test.com')
|
||||
cy.findByRole('button').click()
|
||||
})
|
||||
cy.findByRole('alert').should('contain.text', 'Error: User already added')
|
||||
})
|
||||
|
||||
it('checks the select all checkbox', function () {
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('not.be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('not.be.checked')
|
||||
})
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('thead')
|
||||
.within(() => {
|
||||
cy.findByLabelText(/select all/i).check()
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('remove a member', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 200,
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).check()
|
||||
})
|
||||
})
|
||||
|
||||
cy.findByRole('button', { name: /remove manager/i }).click()
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByText('bobby.lapointe@test.com')
|
||||
cy.findByText('Bobby Lapointe')
|
||||
cy.findByText('2nd Jan 2023')
|
||||
cy.findByText('Accepted invite')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('tries to remove a manager and displays the error', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 500,
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).check()
|
||||
})
|
||||
})
|
||||
cy.findByRole('button', { name: /remove manager/i }).click()
|
||||
|
||||
cy.findByRole('alert').should('contain.text', 'Sorry, something went wrong')
|
||||
})
|
||||
})
|
@@ -0,0 +1,313 @@
|
||||
import GroupMembers from '@/features/group-management/components/group-members'
|
||||
import { GroupMembersProvider } from '@/features/group-management/context/group-members-context'
|
||||
import { User } from '../../../../../types/group-management/user'
|
||||
import { SplitTestProvider } from '@/shared/context/split-test-context'
|
||||
|
||||
const GROUP_ID = '777fff777fff'
|
||||
const JOHN_DOE: User = {
|
||||
_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: User = {
|
||||
_id: 'bcd234efa567',
|
||||
first_name: 'Bobby',
|
||||
last_name: 'Lapointe',
|
||||
email: 'bobby.lapointe@test.com',
|
||||
last_active_at: new Date('2023-01-02'),
|
||||
invite: false,
|
||||
enrollment: {
|
||||
sso: [
|
||||
{
|
||||
groupId: 'another',
|
||||
linkedAt: new Date(),
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
const CLAIRE_JENNINGS: User = {
|
||||
_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: [
|
||||
{
|
||||
groupId: GROUP_ID,
|
||||
linkedAt: new Date(),
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
const PATHS = {
|
||||
addMember: `/manage/groups/${GROUP_ID}/invites`,
|
||||
removeMember: `/manage/groups/${GROUP_ID}/user`,
|
||||
removeInvite: `/manage/groups/${GROUP_ID}/invites`,
|
||||
exportMembers: `/manage/groups/${GROUP_ID}/members/export`,
|
||||
}
|
||||
|
||||
function mountGroupMembersProvider() {
|
||||
cy.mount(
|
||||
<SplitTestProvider>
|
||||
<GroupMembersProvider>
|
||||
<GroupMembers />
|
||||
</GroupMembersProvider>
|
||||
</SplitTestProvider>
|
||||
)
|
||||
}
|
||||
|
||||
describe('group members, with managed users', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
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()
|
||||
})
|
||||
|
||||
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.findByTestId('managed-entities-table')
|
||||
.find('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('.visually-hidden').contains('Pending invite')
|
||||
|
||||
cy.findByTestId('badge-pending-invite').should(
|
||||
'have.text',
|
||||
'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.findByTestId('badge-pending-invite').should('not.exist')
|
||||
cy.get('.visually-hidden').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.findByTestId('badge-pending-invite').should('not.exist')
|
||||
cy.get('.visually-hidden').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.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(4)').within(() => {
|
||||
cy.contains('someone.else@test.com')
|
||||
cy.contains('N/A')
|
||||
cy.get('.visually-hidden').contains('Pending invite')
|
||||
cy.findByTestId('badge-pending-invite').should(
|
||||
'have.text',
|
||||
'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.findByRole('alert').contains('Error: User already added')
|
||||
})
|
||||
|
||||
it('checks the select all checkbox', function () {
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
|
||||
cy.findByTestId('select-all-checkbox').click()
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').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.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').check()
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
|
||||
cy.get('small').contains('You have added 2 of 10 available members')
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('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.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
// no checkbox should be shown for 'Claire Jennings', a managed user
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('tries to remove a user and displays the error', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 500,
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByTestId('select-single-checkbox').check()
|
||||
})
|
||||
})
|
||||
cy.get('.page-header').within(() => {
|
||||
cy.get('button').contains('Remove from group').click()
|
||||
})
|
||||
|
||||
cy.findByRole('alert').contains('Sorry, something went wrong')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Group members when group SSO is enabled', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
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)
|
||||
})
|
||||
})
|
||||
|
||||
it('should not display SSO Column when group sso is not enabled', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', false)
|
||||
})
|
||||
mountGroupMembersProvider()
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.get('.visually-hidden')
|
||||
.contains('SSO not active')
|
||||
.should('not.exist')
|
||||
})
|
||||
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.contains('claire.jennings@test.com')
|
||||
cy.get('.visually-hidden').contains('SSO active').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('should display SSO Column when Group SSO is enabled', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', true)
|
||||
})
|
||||
mountGroupMembersProvider()
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.contains('bobby.lapointe@test.com')
|
||||
cy.get('.visually-hidden').contains('SSO not active')
|
||||
})
|
||||
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.contains('claire.jennings@test.com')
|
||||
cy.get('.visually-hidden').contains('SSO active')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,802 @@
|
||||
import type { PropsWithChildren } from 'react'
|
||||
import sinon from 'sinon'
|
||||
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>>) {
|
||||
return (
|
||||
<table className="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="managed-users-actions" style={{ textAlign: 'right' }}>
|
||||
<GroupMembersProvider>{children}</GroupMembersProvider>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
)
|
||||
}
|
||||
|
||||
function mountDropDownComponent(user: User, subscriptionId: string) {
|
||||
cy.mount(
|
||||
<Wrapper>
|
||||
<DropdownButton
|
||||
user={user}
|
||||
openOffboardingModalForUser={sinon.stub()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
||||
|
||||
describe('DropdownButton', function () {
|
||||
const subscriptionId = '123abc123abc'
|
||||
|
||||
describe('with a standard group', function () {
|
||||
describe('for a pending user (has not joined group)', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: true,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('resend-group-invite-action').should('be.visible')
|
||||
cy.findByTestId('remove-user-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('resend-managed-user-invite-action').should('not.exist')
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('not.exist')
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for the group admin', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {},
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
|
||||
cy.findByTestId('remove-user-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Managed Users enabled', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-managedUsersActive', true)
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a pending user (has not joined group)', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: true,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('resend-group-invite-action').should('be.visible')
|
||||
cy.findByTestId('remove-user-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('resend-managed-user-invite-action').should('not.exist')
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('not.exist')
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a managed group member', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
managedBy: subscriptionId,
|
||||
enrolledAt: new Date(),
|
||||
},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render the dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
|
||||
cy.findByTestId('delete-user-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('remove-user-action').should('not.exist')
|
||||
cy.findByTestId('resend-managed-user-invite-action').should('not.exist')
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('not.exist')
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a non-managed group member', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
|
||||
cy.findByTestId('resend-managed-user-invite-action').should(
|
||||
'be.visible'
|
||||
)
|
||||
cy.findByTestId('remove-user-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('not.exist')
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a managed group admin user', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
managedBy: subscriptionId,
|
||||
enrolledAt: new Date(),
|
||||
},
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render the button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the (empty) menu when the button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('no-actions-available').should('exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Group SSO enabled', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-managedUsersActive', false)
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a pending user (has not joined group)', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: true,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('resend-group-invite-action').should('be.visible')
|
||||
cy.findByTestId('remove-user-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('resend-managed-user-invite-action').should('not.exist')
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('not.exist')
|
||||
cy.findByTestId('unlink-user-action').should('not.exist')
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a group member not linked with SSO yet', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
})
|
||||
|
||||
it('should show resend invite when user is admin', function () {
|
||||
mountDropDownComponent({ ...user, isEntityAdmin: true }, '123abc')
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('exist')
|
||||
})
|
||||
|
||||
it('should not show resend invite when SSO is disabled', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', false)
|
||||
})
|
||||
mountDropDownComponent(user, '123abc')
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('not.exist')
|
||||
})
|
||||
|
||||
it('should show the resend SSO invite option when dropdown button is clicked', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', true)
|
||||
})
|
||||
mountDropDownComponent(user, '123abc')
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('be.visible')
|
||||
})
|
||||
|
||||
it('should make the correct post request when resend SSO invite is clicked ', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', true)
|
||||
})
|
||||
cy.intercept(
|
||||
'POST',
|
||||
'/manage/groups/123abc/resendSSOLinkInvite/some-user',
|
||||
{ success: true }
|
||||
).as('resendInviteRequest')
|
||||
mountDropDownComponent(user, '123abc')
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('resend-sso-link-invite-action')
|
||||
.should('exist')
|
||||
.as('resendInvite')
|
||||
cy.get('@resendInvite').click()
|
||||
cy.wait('@resendInviteRequest')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Managed Users and Group SSO enabled', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-managedUsersActive', true)
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a pending user (has not joined group)', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: true,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('resend-group-invite-action').should('be.visible')
|
||||
cy.findByTestId('remove-user-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('resend-managed-user-invite-action').should('not.exist')
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('not.exist')
|
||||
cy.findByTestId('unlink-user-action').should('not.exist')
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a non-managed group member with SSO linked', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
sso: [
|
||||
{
|
||||
groupId: subscriptionId,
|
||||
linkedAt: new Date(),
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
|
||||
cy.findByTestId('resend-managed-user-invite-action').should(
|
||||
'be.visible'
|
||||
)
|
||||
cy.findByTestId('remove-user-action').should('be.visible')
|
||||
cy.findByTestId('unlink-user-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a non-managed group member with SSO not linked', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
sso: [],
|
||||
},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
|
||||
cy.findByTestId('resend-managed-user-invite-action').should(
|
||||
'be.visible'
|
||||
)
|
||||
cy.findByTestId('remove-user-action').should('be.visible')
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
cy.findByTestId('unlink-user-action').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a non-managed group admin with SSO linked', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
sso: [
|
||||
{
|
||||
groupId: subscriptionId,
|
||||
linkedAt: new Date(),
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
|
||||
cy.findByTestId('resend-managed-user-invite-action').should(
|
||||
'be.visible'
|
||||
)
|
||||
cy.findByTestId('remove-user-action').should('be.visible')
|
||||
cy.findByTestId('unlink-user-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('delete-user-action').should('not.exist')
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('not.exist')
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a non-managed group admin with SSO not linked', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
sso: [],
|
||||
},
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
|
||||
cy.findByTestId('resend-managed-user-invite-action').should(
|
||||
'be.visible'
|
||||
)
|
||||
cy.findByTestId('remove-user-action').should('be.visible')
|
||||
cy.findByTestId('delete-user-action').should('not.exist')
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('exist')
|
||||
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a managed group member with SSO not linked', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
managedBy: subscriptionId,
|
||||
enrolledAt: new Date(),
|
||||
sso: [],
|
||||
},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render the dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
|
||||
cy.findByTestId('delete-user-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('remove-user-action').should('not.exist')
|
||||
cy.findByTestId('resend-managed-user-invite-action').should('not.exist')
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('exist')
|
||||
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a managed group member with SSO linked', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
managedBy: subscriptionId,
|
||||
enrolledAt: new Date(),
|
||||
sso: [
|
||||
{
|
||||
groupId: subscriptionId,
|
||||
linkedAt: new Date(),
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render the dropdown button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
|
||||
cy.findByTestId('delete-user-action').should('be.visible')
|
||||
|
||||
cy.findByTestId('remove-user-action').should('not.exist')
|
||||
cy.findByTestId('resend-managed-user-invite-action').should('not.exist')
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('not.exist')
|
||||
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a managed group admin with SSO not linked', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
managedBy: subscriptionId,
|
||||
enrolledAt: new Date(),
|
||||
sso: [],
|
||||
},
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render the button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show the correct menu when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('exist')
|
||||
|
||||
cy.findByTestId('resend-managed-user-invite-action').should('not.exist')
|
||||
cy.findByTestId('remove-user-action').should('not.exist')
|
||||
cy.findByTestId('delete-user-action').should('not.exist')
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('for a managed group admin with SSO linked', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
managedBy: subscriptionId,
|
||||
enrolledAt: new Date(),
|
||||
sso: [
|
||||
{
|
||||
groupId: subscriptionId,
|
||||
linkedAt: new Date(),
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [user])
|
||||
})
|
||||
|
||||
mountDropDownComponent(user, subscriptionId)
|
||||
})
|
||||
|
||||
it('should render the button', function () {
|
||||
cy.get('#managed-user-dropdown-some\\.user\\@example\\.com').should(
|
||||
'exist'
|
||||
)
|
||||
cy.findByRole('button', { name: /actions/i })
|
||||
})
|
||||
|
||||
it('should show no actions except to unlink when dropdown button is clicked', function () {
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
|
||||
cy.findByTestId('unlink-user-action').should('exist')
|
||||
|
||||
cy.findByTestId('no-actions-available').should('not.exist')
|
||||
cy.findByTestId('delete-user-action').should('not.exist')
|
||||
cy.findByTestId('remove-user-action').should('not.exist')
|
||||
cy.findByTestId('resend-managed-user-invite-action').should('not.exist')
|
||||
cy.findByTestId('resend-sso-link-invite-action').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,86 @@
|
||||
import ManagedUserStatus from '@/features/group-management/components/members-table/managed-user-status'
|
||||
import { User } from '../../../../../../types/group-management/user'
|
||||
|
||||
describe('MemberStatus', function () {
|
||||
describe('with a pending invite', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: true,
|
||||
last_active_at: new Date(),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
beforeEach(function () {
|
||||
cy.mount(<ManagedUserStatus user={user} />)
|
||||
})
|
||||
|
||||
it('should render a pending state', function () {
|
||||
cy.get('.security-state-invite-pending').contains('Managed')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a managed user', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: { managedBy: 'some-group', enrolledAt: new Date() },
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
beforeEach(function () {
|
||||
cy.mount(<ManagedUserStatus user={user} />)
|
||||
})
|
||||
|
||||
it('should render a pending state', function () {
|
||||
cy.get('.security-state-managed').contains('Managed')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with an un-managed user', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
beforeEach(function () {
|
||||
cy.mount(<ManagedUserStatus user={user} />)
|
||||
})
|
||||
|
||||
it('should render an un-managed state', function () {
|
||||
cy.get('.security-state-not-managed').contains('Managed')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with the group admin', function () {
|
||||
const user: User = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: true,
|
||||
}
|
||||
beforeEach(function () {
|
||||
cy.mount(<ManagedUserStatus user={user} />)
|
||||
})
|
||||
|
||||
it('should render no state indicator', function () {
|
||||
cy.get('.security-state-group-admin')
|
||||
.contains('Managed')
|
||||
.should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,710 @@
|
||||
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 () {
|
||||
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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the row', function () {
|
||||
cy.get('tr')
|
||||
// Checkbox
|
||||
cy.findByTestId('select-single-checkbox').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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Pending invite" badge', function () {
|
||||
cy.findByTestId('badge-pending-invite').should(
|
||||
'have.text',
|
||||
'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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Group admin" symbol', function () {
|
||||
cy.findByTestId('group-admin-symbol').within(() => {
|
||||
cy.findByText(/group admin/i)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should select and unselect the user', function () {
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
cy.findByTestId('select-single-checkbox').click()
|
||||
cy.findByTestId('select-single-checkbox').should('be.checked')
|
||||
cy.findByTestId('select-single-checkbox').click()
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Managed Users enabled', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the row', function () {
|
||||
cy.get('tr').should('exist')
|
||||
// Checkbox
|
||||
cy.findByTestId('select-single-checkbox').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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Pending invite" badge', function () {
|
||||
cy.findByTestId('badge-pending-invite').should(
|
||||
'have.text',
|
||||
'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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Group admin" symbol', function () {
|
||||
cy.findByTestId('group-admin-symbol').within(() => {
|
||||
cy.findByText(/group admin/i)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should select and unselect the user', function () {
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
cy.findByTestId('select-single-checkbox').click()
|
||||
cy.findByTestId('select-single-checkbox').should('be.checked')
|
||||
cy.findByTestId('select-single-checkbox').click()
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Group SSO enabled', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the row', function () {
|
||||
// Checkbox
|
||||
cy.findByTestId('select-single-checkbox').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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Pending invite" badge', function () {
|
||||
cy.findByTestId('badge-pending-invite').should(
|
||||
'have.text',
|
||||
'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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Group admin" symbol', function () {
|
||||
cy.findByTestId('group-admin-symbol').within(() => {
|
||||
cy.findByText(/group admin/i)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should select and unselect the user', function () {
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
cy.findByTestId('select-single-checkbox').click()
|
||||
cy.findByTestId('select-single-checkbox').should('be.checked')
|
||||
cy.findByTestId('select-single-checkbox').click()
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Managed Users and Group SSO enabled', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the row', function () {
|
||||
// Checkbox
|
||||
cy.findByTestId('select-single-checkbox').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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Pending invite" badge', function () {
|
||||
cy.findByTestId('badge-pending-invite').should(
|
||||
'have.text',
|
||||
'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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render a "Group admin" symbol', function () {
|
||||
cy.findByTestId('group-admin-symbol').within(() => {
|
||||
cy.findByText(/group admin/i)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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()}
|
||||
openUnlinkUserModal={sinon.stub()}
|
||||
groupId={subscriptionId}
|
||||
setGroupUserAlert={sinon.stub()}
|
||||
/>
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should select and unselect the user', function () {
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
cy.findByTestId('select-single-checkbox').click()
|
||||
cy.findByTestId('select-single-checkbox').should('be.checked')
|
||||
cy.findByTestId('select-single-checkbox').click()
|
||||
cy.findByTestId('select-single-checkbox').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,332 @@
|
||||
import MembersList from '@/features/group-management/components/members-table/members-list'
|
||||
import { GroupMembersProvider } from '@/features/group-management/context/group-members-context'
|
||||
import { User } from '../../../../../../types/group-management/user'
|
||||
|
||||
const groupId = 'somegroup'
|
||||
|
||||
function mountManagedUsersList() {
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MembersList groupId={groupId} />
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
}
|
||||
|
||||
describe('MembersList', function () {
|
||||
describe('with users', function () {
|
||||
const users = [
|
||||
{
|
||||
_id: 'user-one',
|
||||
email: 'sarah.brennan@example.com',
|
||||
first_name: 'Sarah',
|
||||
last_name: 'Brennan',
|
||||
invite: false,
|
||||
last_active_at: new Date('2070-10-22T03:00:00'),
|
||||
enrollment: undefined,
|
||||
isEntityAdmin: undefined,
|
||||
},
|
||||
{
|
||||
_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,
|
||||
},
|
||||
]
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', users)
|
||||
})
|
||||
mountManagedUsersList()
|
||||
})
|
||||
|
||||
it('should render the table headers but not SSO Column', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', false)
|
||||
})
|
||||
mountManagedUsersList()
|
||||
|
||||
// Select-all checkbox
|
||||
cy.findByTestId('managed-entities-table').within(() => {
|
||||
cy.findByTestId('select-all-checkbox')
|
||||
})
|
||||
cy.findByTestId('managed-entities-table').should('contain.text', 'Email')
|
||||
cy.findByTestId('managed-entities-table').should('contain.text', 'Name')
|
||||
cy.findByTestId('managed-entities-table').should(
|
||||
'contain.text',
|
||||
'Last Active'
|
||||
)
|
||||
cy.findByTestId('managed-entities-table').should(
|
||||
'not.contain.text',
|
||||
'Security'
|
||||
)
|
||||
})
|
||||
it('should render the table headers with SSO Column', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', true)
|
||||
})
|
||||
mountManagedUsersList()
|
||||
|
||||
// Select-all checkbox
|
||||
cy.findByTestId('managed-entities-table').within(() => {
|
||||
cy.findByTestId('select-all-checkbox')
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table').should('contain.text', 'Email')
|
||||
cy.findByTestId('managed-entities-table').should('contain.text', 'Name')
|
||||
cy.findByTestId('managed-entities-table').should(
|
||||
'contain.text',
|
||||
'Last Active'
|
||||
)
|
||||
cy.findByTestId('managed-entities-table').should(
|
||||
'contain.text',
|
||||
'Security'
|
||||
)
|
||||
})
|
||||
|
||||
it('should render the list of users', function () {
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.findAllByRole('row').should('have.length', 2)
|
||||
})
|
||||
// First user
|
||||
cy.findByTestId('managed-entities-table').should(
|
||||
'contain.text',
|
||||
users[0].email
|
||||
)
|
||||
cy.findByTestId('managed-entities-table').should(
|
||||
'contain.text',
|
||||
users[0].first_name
|
||||
)
|
||||
cy.findByTestId('managed-entities-table').should(
|
||||
'contain.text',
|
||||
users[0].last_name
|
||||
)
|
||||
// Second user
|
||||
cy.findByTestId('managed-entities-table').should(
|
||||
'contain.text',
|
||||
users[1].email
|
||||
)
|
||||
cy.findByTestId('managed-entities-table').should(
|
||||
'contain.text',
|
||||
users[1].first_name
|
||||
)
|
||||
cy.findByTestId('managed-entities-table').should(
|
||||
'contain.text',
|
||||
users[1].last_name
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('empty user list', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [])
|
||||
})
|
||||
cy.mount(
|
||||
<GroupMembersProvider>
|
||||
<MembersList groupId={groupId} />
|
||||
</GroupMembersProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render the list, with a "no members" message', function () {
|
||||
cy.findByTestId('managed-entities-table').should(
|
||||
'contain.text',
|
||||
'No members'
|
||||
)
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.findAllByRole('row')
|
||||
.should('have.length', 1)
|
||||
.and('contain.text', 'No members')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('SSO unlinking', function () {
|
||||
const USER_PENDING_INVITE: User = {
|
||||
_id: 'abc123def456',
|
||||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
email: 'john.doe@test.com',
|
||||
last_active_at: new Date('2023-01-15'),
|
||||
invite: true,
|
||||
}
|
||||
const USER_NOT_LINKED: User = {
|
||||
_id: 'bcd234efa567',
|
||||
first_name: 'Bobby',
|
||||
last_name: 'Lapointe',
|
||||
email: 'bobby.lapointe@test.com',
|
||||
last_active_at: new Date('2023-01-02'),
|
||||
invite: false,
|
||||
}
|
||||
const USER_LINKED: User = {
|
||||
_id: 'defabc231453',
|
||||
first_name: 'Claire',
|
||||
last_name: 'Jennings',
|
||||
email: 'claire.jennings@test.com',
|
||||
last_active_at: new Date('2023-01-03'),
|
||||
invite: false,
|
||||
enrollment: {
|
||||
sso: [
|
||||
{
|
||||
groupId,
|
||||
linkedAt: new Date('2023-01-03'),
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
const USER_LINKED_AND_MANAGED: User = {
|
||||
_id: 'defabc231453',
|
||||
first_name: 'Jean-Luc',
|
||||
last_name: 'Picard',
|
||||
email: 'picard@test.com',
|
||||
last_active_at: new Date('2023-01-03'),
|
||||
invite: false,
|
||||
enrollment: {
|
||||
managedBy: groupId,
|
||||
enrolledAt: new Date('2023-01-03'),
|
||||
sso: [
|
||||
{
|
||||
groupId,
|
||||
linkedAt: new Date('2023-01-03'),
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
const users = [
|
||||
USER_PENDING_INVITE,
|
||||
USER_NOT_LINKED,
|
||||
USER_LINKED,
|
||||
USER_LINKED_AND_MANAGED,
|
||||
]
|
||||
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupId', groupId)
|
||||
win.metaAttributesCache.set('ol-users', users)
|
||||
win.metaAttributesCache.set('ol-groupSSOActive', true)
|
||||
})
|
||||
|
||||
cy.intercept('POST', `manage/groups/${groupId}/unlink-user/*`, {
|
||||
statusCode: 200,
|
||||
})
|
||||
})
|
||||
|
||||
describe('unlinking user', function () {
|
||||
beforeEach(function () {
|
||||
mountManagedUsersList()
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.findByText('SSO active')
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('unlink-user-action').click()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('should show successs notification and update the user row after unlinking', function () {
|
||||
cy.findByRole('dialog').within(() => {
|
||||
cy.findByRole('button', { name: /unlink user/i }).click()
|
||||
})
|
||||
cy.findByRole('alert').should(
|
||||
'contain.text',
|
||||
`SSO reauthentication request has been sent to ${USER_LINKED.email}`
|
||||
)
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.findByText('SSO not active')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('managed users enabled', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-managedUsersActive', true)
|
||||
})
|
||||
mountManagedUsersList()
|
||||
})
|
||||
|
||||
describe('when user is not managed', function () {
|
||||
beforeEach(function () {
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.findByText('SSO active')
|
||||
cy.findByText('Not managed')
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('unlink-user-action').click()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('should show successs notification and update the user row after unlinking', function () {
|
||||
cy.findByRole('dialog').within(() => {
|
||||
cy.findByRole('button', { name: /unlink user/i }).click()
|
||||
})
|
||||
cy.findByRole('alert').should(
|
||||
'contain.text',
|
||||
`SSO reauthentication request has been sent to ${USER_LINKED.email}`
|
||||
)
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.findByText('SSO not active')
|
||||
cy.findByText('Not managed')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when user is managed', function () {
|
||||
beforeEach(function () {
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(4)').within(() => {
|
||||
cy.findByText('SSO active')
|
||||
cy.findAllByText('Managed')
|
||||
cy.findByRole('button', { name: /actions/i }).click()
|
||||
cy.findByTestId('unlink-user-action').click()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('should show successs notification and update the user row after unlinking', function () {
|
||||
cy.findByRole('dialog').within(() => {
|
||||
cy.findByRole('button', { name: /unlink user/i }).click()
|
||||
})
|
||||
cy.findByRole('alert').should(
|
||||
'contain.text',
|
||||
`SSO reauthentication request has been sent to ${USER_LINKED_AND_MANAGED.email}`
|
||||
)
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(4)').within(() => {
|
||||
cy.findByText('SSO not active')
|
||||
cy.findAllByText('Managed')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,107 @@
|
||||
import OffboardManagedUserModal from '@/features/group-management/components/members-table/offboard-managed-user-modal'
|
||||
import sinon from 'sinon'
|
||||
|
||||
describe('OffboardManagedUserModal', function () {
|
||||
describe('happy path', function () {
|
||||
const groupId = 'some-group'
|
||||
const user = {
|
||||
_id: 'some-user',
|
||||
email: 'some.user@example.com',
|
||||
first_name: 'Some',
|
||||
last_name: 'User',
|
||||
invite: true,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
managedBy: `${groupId}`,
|
||||
enrolledAt: new Date(),
|
||||
},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
const otherUser = {
|
||||
_id: 'other-user',
|
||||
email: 'other.user@example.com',
|
||||
first_name: 'Other',
|
||||
last_name: 'User',
|
||||
invite: false,
|
||||
last_active_at: new Date(),
|
||||
enrollment: {
|
||||
managedBy: `${groupId}`,
|
||||
enrolledAt: new Date(),
|
||||
},
|
||||
isEntityAdmin: undefined,
|
||||
}
|
||||
const allMembers = [user, otherUser]
|
||||
|
||||
beforeEach(function () {
|
||||
cy.mount(
|
||||
<OffboardManagedUserModal
|
||||
user={user}
|
||||
allMembers={allMembers}
|
||||
groupId={groupId}
|
||||
onClose={sinon.stub()}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
it('should render the modal', function () {
|
||||
cy.get('#delete-user-form').should('exist')
|
||||
})
|
||||
|
||||
it('should disable the button if a recipient is not selected', function () {
|
||||
// Button should be disabled initially
|
||||
cy.get('button[type="submit"]').should('be.disabled')
|
||||
|
||||
// Not selecting a recipient...
|
||||
|
||||
// Fill in the email input
|
||||
cy.get('#supplied-email-input').type(user.email)
|
||||
|
||||
// Button still disabled
|
||||
cy.get('button[type="submit"]').should('be.disabled')
|
||||
})
|
||||
|
||||
it('should disable the button if the email is not filled in', function () {
|
||||
// Button should be disabled initially
|
||||
cy.get('button[type="submit"]').should('be.disabled')
|
||||
|
||||
// Select a recipient
|
||||
cy.get('#recipient-select-input').select('other.user@example.com')
|
||||
|
||||
// Not filling in the email...
|
||||
|
||||
// Button still disabled
|
||||
cy.get('button[type="submit"]').should('be.disabled')
|
||||
})
|
||||
|
||||
it('should disable the button if the email does not match the user', function () {
|
||||
// Button should be disabled initially
|
||||
cy.get('button[type="submit"]').should('be.disabled')
|
||||
|
||||
// Select a recipient
|
||||
cy.get('#recipient-select-input').select('other.user@example.com')
|
||||
|
||||
// Fill in the email input, with the wrong email address
|
||||
cy.get('#supplied-email-input').type('totally.wrong@example.com')
|
||||
|
||||
// Button still disabled
|
||||
cy.get('button[type="submit"]').should('be.disabled')
|
||||
})
|
||||
|
||||
it('should fill out the form, and enable the delete button', function () {
|
||||
// Button should be disabled initially
|
||||
cy.get('button[type="submit"]').should('be.disabled')
|
||||
|
||||
// Select a recipient
|
||||
cy.get('#recipient-select-input').select('other.user@example.com')
|
||||
|
||||
// Button still disabled
|
||||
cy.get('button[type="submit"]').should('be.disabled')
|
||||
|
||||
// Fill in the email input
|
||||
cy.get('#supplied-email-input').type(user.email)
|
||||
|
||||
// Button should be enabled now
|
||||
cy.get('button[type="submit"]').should('not.be.disabled')
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,74 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { ReactElement } from 'react'
|
||||
import sinon from 'sinon'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import UnlinkUserModal from '@/features/group-management/components/members-table/unlink-user-modal'
|
||||
import { GroupMembersProvider } from '@/features/group-management/context/group-members-context'
|
||||
import { expect } from 'chai'
|
||||
|
||||
export function renderWithContext(component: ReactElement, props = {}) {
|
||||
const GroupMembersProviderWrapper = ({
|
||||
children,
|
||||
}: {
|
||||
children: ReactElement
|
||||
}) => <GroupMembersProvider {...props}>{children}</GroupMembersProvider>
|
||||
|
||||
return render(component, { wrapper: GroupMembersProviderWrapper })
|
||||
}
|
||||
|
||||
describe('<UnlinkUserModal />', function () {
|
||||
let defaultProps: any
|
||||
const groupId = 'group123'
|
||||
const userId = 'user123'
|
||||
|
||||
beforeEach(function () {
|
||||
defaultProps = {
|
||||
onClose: sinon.stub(),
|
||||
user: { _id: userId },
|
||||
setGroupUserAlert: sinon.stub(),
|
||||
}
|
||||
window.metaAttributesCache.set('ol-groupId', groupId)
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
fetchMock.removeRoutes().clearHistory()
|
||||
})
|
||||
|
||||
it('displays the modal', async function () {
|
||||
renderWithContext(<UnlinkUserModal {...defaultProps} />)
|
||||
await screen.findByRole('heading', {
|
||||
name: 'Unlink user',
|
||||
})
|
||||
screen.getByText('You’re about to remove the SSO login option for', {
|
||||
exact: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('closes the modal on success', async function () {
|
||||
fetchMock.post(`/manage/groups/${groupId}/unlink-user/${userId}`, 200)
|
||||
|
||||
renderWithContext(<UnlinkUserModal {...defaultProps} />)
|
||||
await screen.findByRole('heading', {
|
||||
name: 'Unlink user',
|
||||
})
|
||||
|
||||
const confirmButton = screen.getByRole('button', { name: 'Unlink user' })
|
||||
fireEvent.click(confirmButton)
|
||||
|
||||
await waitFor(() => expect(defaultProps.onClose).to.have.been.called)
|
||||
})
|
||||
|
||||
it('handles errors', async function () {
|
||||
fetchMock.post(`/manage/groups/${groupId}/unlink-user/${userId}`, 500)
|
||||
|
||||
renderWithContext(<UnlinkUserModal {...defaultProps} />)
|
||||
await screen.findByRole('heading', {
|
||||
name: 'Unlink user',
|
||||
})
|
||||
|
||||
const confirmButton = screen.getByRole('button', { name: 'Unlink user' })
|
||||
fireEvent.click(confirmButton)
|
||||
|
||||
await waitFor(() => screen.findByText('Sorry, something went wrong'))
|
||||
})
|
||||
})
|
@@ -0,0 +1,38 @@
|
||||
import { SplitTestProvider } from '@/shared/context/split-test-context'
|
||||
import MissingBillingInformation from '@/features/group-management/components/missing-billing-information'
|
||||
|
||||
describe('<MissingBillingInformation />', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Team')
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<SplitTestProvider>
|
||||
<MissingBillingInformation />
|
||||
</SplitTestProvider>
|
||||
)
|
||||
})
|
||||
|
||||
it('shows missing payment details notification', function () {
|
||||
cy.findByRole('alert').within(() => {
|
||||
cy.findByText(/missing payment details/i)
|
||||
cy.findByText(
|
||||
/it looks like your payment details are missing\. Please.*, or.*with our Support team for more help/i
|
||||
).within(() => {
|
||||
cy.findByRole('link', {
|
||||
name: /update your billing information/i,
|
||||
}).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/user/subscription/recurly/billing-details'
|
||||
)
|
||||
cy.findByRole('link', { name: /get in touch/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/contact'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,171 @@
|
||||
import PublisherManagers from '@/features/group-management/components/publisher-managers'
|
||||
|
||||
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 = '000fff000fff'
|
||||
const PATHS = {
|
||||
addMember: `/manage/publishers/${GROUP_ID}/managers`,
|
||||
removeMember: `/manage/publishers/${GROUP_ID}/managers`,
|
||||
}
|
||||
|
||||
describe('publisher managers', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-users', [JOHN_DOE, BOBBY_LAPOINTE])
|
||||
win.metaAttributesCache.set('ol-groupId', GROUP_ID)
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Publisher')
|
||||
})
|
||||
|
||||
cy.mount(<PublisherManagers />)
|
||||
})
|
||||
|
||||
it('renders the publisher management page', function () {
|
||||
cy.findByRole('heading', { name: /my awesome publisher/i, level: 1 })
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByText('john.doe@test.com')
|
||||
cy.findByText('John Doe')
|
||||
cy.findByText('15th Jan 2023')
|
||||
cy.findByText('Invite not yet accepted')
|
||||
})
|
||||
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByText('bobby.lapointe@test.com')
|
||||
cy.findByText('Bobby Lapointe')
|
||||
cy.findByText('2nd Jan 2023')
|
||||
cy.findByText('Accepted invite')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('sends an invite', function () {
|
||||
cy.intercept('POST', PATHS.addMember, {
|
||||
statusCode: 201,
|
||||
body: {
|
||||
user: {
|
||||
email: 'someone.else@test.com',
|
||||
invite: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
cy.findByTestId('add-members-form').within(() => {
|
||||
cy.findByRole('textbox').type('someone.else@test.com')
|
||||
cy.findByRole('button').click()
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(3)').within(() => {
|
||||
cy.findByText('someone.else@test.com')
|
||||
cy.findByText('N/A')
|
||||
cy.findByText('Invite not yet accepted')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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.findByTestId('add-members-form').within(() => {
|
||||
cy.findByRole('textbox').type('someone.else@test.com')
|
||||
cy.findByRole('button').click()
|
||||
})
|
||||
cy.findByRole('alert').should('contain.text', 'Error: User already added')
|
||||
})
|
||||
|
||||
it('checks the select all checkbox', function () {
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('not.be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('not.be.checked')
|
||||
})
|
||||
})
|
||||
|
||||
cy.findByTestId('select-all-checkbox').click()
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('be.checked')
|
||||
})
|
||||
cy.get('tr:nth-child(2)').within(() => {
|
||||
cy.findByLabelText(/select user/i).should('be.checked')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('remove a member', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 200,
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).check()
|
||||
})
|
||||
})
|
||||
|
||||
cy.findByRole('button', { name: 'Remove manager' }).click()
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByText('bobby.lapointe@test.com')
|
||||
cy.findByText('Bobby Lapointe')
|
||||
cy.findByText('2nd Jan 2023')
|
||||
cy.findByText('Accepted invite')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('tries to remove a manager and displays the error', function () {
|
||||
cy.intercept('DELETE', `${PATHS.removeMember}/abc123def456`, {
|
||||
statusCode: 500,
|
||||
})
|
||||
|
||||
cy.findByTestId('managed-entities-table')
|
||||
.find('tbody')
|
||||
.within(() => {
|
||||
cy.get('tr:nth-child(1)').within(() => {
|
||||
cy.findByLabelText(/select user/i).check()
|
||||
})
|
||||
})
|
||||
cy.findByRole('button', { name: /remove manager/i }).click()
|
||||
|
||||
cy.findByRole('alert').should('contain.text', 'Sorry, something went wrong')
|
||||
})
|
||||
})
|
@@ -0,0 +1,44 @@
|
||||
import RequestStatus from '@/features/group-management/components/request-status'
|
||||
|
||||
describe('<RequestStatus />', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Team')
|
||||
})
|
||||
cy.mount(
|
||||
<RequestStatus icon="email" title="Test title" content="Test content" />
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the back button', function () {
|
||||
cy.findByTestId('group-heading').within(() => {
|
||||
cy.findByRole('button', { name: /back to subscription/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/user/subscription'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('shows the group name', function () {
|
||||
cy.findByTestId('group-heading').within(() => {
|
||||
cy.findByRole('heading', { name: 'My Awesome Team' })
|
||||
})
|
||||
})
|
||||
|
||||
it('shows the title', function () {
|
||||
cy.findByTestId('title').should('contain.text', 'Test title')
|
||||
})
|
||||
|
||||
it('shows the content', function () {
|
||||
cy.findByText('Test content')
|
||||
})
|
||||
|
||||
it('renders the link to subscriptions', function () {
|
||||
cy.findByRole('button', { name: /go to subscriptions/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/user/subscription'
|
||||
)
|
||||
})
|
||||
})
|
@@ -0,0 +1,23 @@
|
||||
import SubtotalLimitExceeded from '@/features/group-management/components/subtotal-limit-exceeded'
|
||||
|
||||
describe('<SubtotalLimitExceeded />', function () {
|
||||
beforeEach(function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Team')
|
||||
})
|
||||
|
||||
cy.mount(<SubtotalLimitExceeded />)
|
||||
})
|
||||
|
||||
it('shows subtotal limit exceeded notification', function () {
|
||||
cy.findByRole('alert').within(() => {
|
||||
cy.findByText(
|
||||
/sorry, there was an issue upgrading your subscription\. Please.*for help/i
|
||||
).within(() => {
|
||||
cy.findByRole('link', {
|
||||
name: /contact our support team/i,
|
||||
}).should('have.attr', 'href', '/contact')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,150 @@
|
||||
import UpgradeSubscription from '@/features/group-management/components/upgrade-subscription/upgrade-subscription'
|
||||
import { SubscriptionChangePreview } from '../../../../../types/subscription/subscription-change-preview'
|
||||
|
||||
describe('<UpgradeSubscription />', function () {
|
||||
const resetPreviewAndRemount = (preview: SubscriptionChangePreview) => {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-subscriptionChangePreview', preview)
|
||||
})
|
||||
|
||||
cy.mount(<UpgradeSubscription />)
|
||||
}
|
||||
beforeEach(function () {
|
||||
this.totalLicenses = 2
|
||||
this.preview = {
|
||||
change: {
|
||||
type: 'group-plan-upgrade',
|
||||
prevPlan: { name: 'Overleaf Standard Group' },
|
||||
},
|
||||
currency: 'USD',
|
||||
immediateCharge: {
|
||||
subtotal: 353.99,
|
||||
tax: 70.8,
|
||||
total: 424.79,
|
||||
discount: 0,
|
||||
},
|
||||
paymentMethod: 'Visa **** 1111',
|
||||
nextPlan: { annual: true },
|
||||
nextInvoice: {
|
||||
date: '2025-11-05T11:35:32.000Z',
|
||||
plan: { name: 'Overleaf Professional Group', amount: 0 },
|
||||
addOns: [
|
||||
{
|
||||
code: 'additional-license',
|
||||
name: 'Seat',
|
||||
quantity: 2,
|
||||
unitAmount: 399,
|
||||
amount: 798,
|
||||
},
|
||||
],
|
||||
subtotal: 798,
|
||||
tax: { rate: 0.2, amount: 159.6 },
|
||||
total: 957.6,
|
||||
},
|
||||
}
|
||||
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-groupName', 'My Awesome Team')
|
||||
win.metaAttributesCache.set('ol-totalLicenses', this.totalLicenses)
|
||||
})
|
||||
resetPreviewAndRemount(this.preview)
|
||||
})
|
||||
|
||||
it('shows the group name', function () {
|
||||
cy.findByTestId('group-heading').within(() => {
|
||||
cy.findByRole('heading', { name: 'My Awesome Team' })
|
||||
})
|
||||
})
|
||||
|
||||
it('shows the "Add more licenses to my plan" label', function () {
|
||||
cy.findByText(/add more licenses to my plan/i).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/user/subscription/group/add-users'
|
||||
)
|
||||
})
|
||||
|
||||
it('shows the "Upgrade" and "Cancel" buttons', function () {
|
||||
cy.findByRole('button', { name: /upgrade/i })
|
||||
cy.findByRole('button', { name: /cancel/i }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/user/subscription'
|
||||
)
|
||||
})
|
||||
|
||||
describe('shows plan details', function () {
|
||||
it('shows per user price', function () {
|
||||
cy.findByTestId('per-user-price').within(() => {
|
||||
cy.findByText('$399')
|
||||
})
|
||||
})
|
||||
|
||||
it('shows additional features', function () {
|
||||
cy.findByText(/unlimited collaborators per project/i)
|
||||
cy.findByText(/sso/i)
|
||||
cy.findByText(/managed user accounts/i)
|
||||
})
|
||||
})
|
||||
|
||||
describe('shows upgrade summary', function () {
|
||||
it('shows subtotal, tax and total price', function () {
|
||||
cy.findByTestId('subtotal').within(() => {
|
||||
cy.findByText('$353.99')
|
||||
})
|
||||
cy.findByTestId('tax').within(() => {
|
||||
cy.findByText('$70.80')
|
||||
})
|
||||
cy.findByTestId('total').within(() => {
|
||||
cy.findByText('$424.79')
|
||||
})
|
||||
cy.findByTestId('discount').should('not.exist')
|
||||
})
|
||||
|
||||
it('shows subtotal, discount, tax and total price', function () {
|
||||
resetPreviewAndRemount({
|
||||
...this.preview,
|
||||
immediateCharge: {
|
||||
subtotal: 353.99,
|
||||
tax: 70.8,
|
||||
total: 424.79,
|
||||
discount: 50,
|
||||
},
|
||||
})
|
||||
cy.findByTestId('subtotal').within(() => {
|
||||
cy.findByText('$353.99')
|
||||
})
|
||||
cy.findByTestId('tax').within(() => {
|
||||
cy.findByText('$70.80')
|
||||
})
|
||||
cy.findByTestId('total').within(() => {
|
||||
cy.findByText('$424.79')
|
||||
})
|
||||
cy.findByTestId('discount').within(() => {
|
||||
cy.findByText('($50.00)')
|
||||
})
|
||||
})
|
||||
|
||||
it('shows total users', function () {
|
||||
cy.findByText(/you have 2 licenses on your subscription./i)
|
||||
})
|
||||
})
|
||||
|
||||
describe('submit upgrade request', function () {
|
||||
it('request succeeded', function () {
|
||||
cy.intercept('POST', '/user/subscription/group/upgrade-subscription', {
|
||||
statusCode: 200,
|
||||
}).as('upgradeRequest')
|
||||
cy.findByRole('button', { name: /upgrade/i }).click()
|
||||
cy.findByText(/you’ve upgraded your plan!/i)
|
||||
})
|
||||
|
||||
it('request failed', function () {
|
||||
cy.intercept('POST', '/user/subscription/group/upgrade-subscription', {
|
||||
statusCode: 400,
|
||||
}).as('upgradeRequest')
|
||||
cy.findByRole('button', { name: /upgrade/i }).click()
|
||||
cy.findByText(/something went wrong/i)
|
||||
})
|
||||
})
|
||||
})
|
Reference in New Issue
Block a user