0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-27 22:49:56 -05:00
ghost/apps/admin-x-settings/test/e2e/general/users/actions.test.ts
Jono M 0e35baaf01
Refactored limit=all queries to be paginated in AdminX (#18324)
refs https://github.com/TryGhost/Product/issues/3832

---

### <samp>🤖 Generated by Copilot at 0095d23</samp>

The pull request adds support for asynchronous and creatable select
inputs in various components, using the `react-select` and
`@tanstack/react-query` libraries. It also adds pagination features to
the newsletters and tiers lists, using a `Button` component and infinite
queries. It refactors and fixes the type and null handling of the select
inputs and their options, using the `SelectOption` type and the
`useFilterableApi` and `debounce` hooks. It removes some unnecessary
props from the browse queries, and adds a new custom hook
`useDefaultRecipientsOptions` for the default recipients component. It
updates the stories and modals to use the new select inputs and options.
2023-09-25 14:03:47 +01:00

256 lines
10 KiB
TypeScript

import {expect, test} from '@playwright/test';
import {globalDataRequests, limitRequests, mockApi, responseFixtures} from '../../../utils/e2e';
test.describe('User actions', async () => {
test('Supports suspending a user', async ({page}) => {
const userToEdit = responseFixtures.users.users.find(user => user.email === 'author@test.com')!;
const {lastApiRequests} = await mockApi({page, requests: {
...globalDataRequests,
browseUsers: {method: 'GET', path: '/users/?limit=100&include=roles', response: responseFixtures.users},
editUser: {method: 'PUT', path: `/users/${userToEdit.id}/?include=roles`, response: {
users: [{
...userToEdit,
status: 'inactive'
}]
}}
}});
await page.goto('/');
const section = page.getByTestId('users');
const activeTab = section.locator('[role=tabpanel]:not(.hidden)');
await section.getByRole('tab', {name: 'Authors'}).click();
const listItem = activeTab.getByTestId('user-list-item').last();
await listItem.hover();
await listItem.getByRole('button', {name: 'Edit'}).click();
const modal = page.getByTestId('user-detail-modal');
await modal.getByRole('button', {name: 'Actions'}).click();
await page.getByTestId('popover-content').getByRole('button', {name: 'Suspend user'}).click();
const confirmation = page.getByTestId('confirmation-modal');
await confirmation.getByRole('button', {name: 'Suspend'}).click();
await expect(modal).toHaveText(/Suspended/);
expect(lastApiRequests.editUser?.body).toMatchObject({
users: [{
email: 'author@test.com',
status: 'inactive'
}]
});
});
test('Supports un-suspending a user', async ({page}) => {
const userToEdit = responseFixtures.users.users.find(user => user.email === 'author@test.com')!;
const {lastApiRequests} = await mockApi({page, requests: {
...globalDataRequests,
browseUsers: {method: 'GET', path: '/users/?limit=100&include=roles', response: {
users: [
...responseFixtures.users.users.filter(user => user.email !== 'author@test.com'),
{
...userToEdit,
status: 'inactive'
}
]
}},
editUser: {method: 'PUT', path: `/users/${userToEdit.id}/?include=roles`, response: {
users: [{
...userToEdit,
status: 'active'
}]
}}
}});
await page.goto('/');
const section = page.getByTestId('users');
const activeTab = section.locator('[role=tabpanel]:not(.hidden)');
await section.getByRole('tab', {name: 'Authors'}).click();
const listItem = activeTab.getByTestId('user-list-item').last();
await listItem.hover();
await listItem.getByRole('button', {name: 'Edit'}).click();
const modal = page.getByTestId('user-detail-modal');
await expect(modal).toHaveText(/Suspended/);
await modal.getByRole('button', {name: 'Actions'}).click();
await page.getByTestId('popover-content').getByRole('button', {name: 'Un-suspend user'}).click();
const confirmation = page.getByTestId('confirmation-modal');
await confirmation.getByRole('button', {name: 'Un-suspend'}).click();
await expect(modal).not.toHaveText(/Suspended/);
expect(lastApiRequests.editUser?.body).toMatchObject({
users: [{
email: 'author@test.com',
status: 'active'
}]
});
});
test('Supports deleting a user', async ({page}) => {
const authorUser = responseFixtures.users.users.find(user => user.email === 'author@test.com')!;
const {lastApiRequests} = await mockApi({page, requests: {
...globalDataRequests,
browseUsers: {method: 'GET', path: '/users/?limit=100&include=roles', response: responseFixtures.users},
deleteUser: {method: 'DELETE', path: `/users/${authorUser.id}/`, response: {}}
}});
await page.goto('/');
const section = page.getByTestId('users');
const activeTab = section.locator('[role=tabpanel]:not(.hidden)');
await section.getByRole('tab', {name: 'Authors'}).click();
const listItem = activeTab.getByTestId('user-list-item').last();
await listItem.hover();
await listItem.getByRole('button', {name: 'Edit'}).click();
const modal = page.getByTestId('user-detail-modal');
await modal.getByRole('button', {name: 'Actions'}).click();
await page.getByTestId('popover-content').getByRole('button', {name: 'Delete user'}).click();
const confirmation = page.getByTestId('confirmation-modal');
await confirmation.getByRole('button', {name: 'Delete user'}).click();
await expect(page.getByTestId('toast-success')).toHaveText(/User deleted/);
await expect(activeTab.getByTestId('user-list-item')).toHaveCount(0);
expect(lastApiRequests.deleteUser?.url).toMatch(new RegExp(`/users/${authorUser.id}`));
});
test('Supports transferring ownership to an administrator', async ({page}) => {
const administrator = responseFixtures.users.users.find(user => user.email === 'administrator@test.com')!;
const makeOwnerResponse = {
users: [
...responseFixtures.users.users.filter(user => user.email !== 'administrator@test.com' && user.email !== 'owner@test.com'),
{
...administrator,
roles: [responseFixtures.roles.roles.find(role => role.name === 'Owner')!]
},
{
...responseFixtures.users.users.find(user => user.email === 'owner@test.com')!,
roles: [responseFixtures.roles.roles.find(role => role.name === 'Administrator')!]
}
]
};
const {lastApiRequests} = await mockApi({page, requests: {
...globalDataRequests,
browseUsers: {method: 'GET', path: '/users/?limit=100&include=roles', response: responseFixtures.users},
editUser: {method: 'PUT', path: /^\/users\/\w{24}\/\?include=roles$/, response: responseFixtures.users},
makeOwner: {method: 'PUT', path: '/users/owner/', response: makeOwnerResponse}
}});
await page.goto('/');
const section = page.getByTestId('users');
const activeTab = section.locator('[role=tabpanel]:not(.hidden)');
const listItem = activeTab.getByTestId('user-list-item').last();
const modal = page.getByTestId('user-detail-modal');
// Can't transfer to a role other than administrator
await section.getByRole('tab', {name: 'Editors'}).click();
await listItem.hover();
await listItem.getByRole('button', {name: 'Edit'}).click();
await modal.getByRole('button', {name: 'Actions'}).click();
await expect(page.getByTestId('popover-content').getByRole('button', {name: 'Make owner'})).toHaveCount(0);
await page.getByTestId('popover-overlay').click();
await modal.getByRole('button', {name: 'Close'}).click();
// Can transfer to an administrator
await section.getByRole('tab', {name: 'Administrators'}).click();
await listItem.hover();
await listItem.getByRole('button', {name: 'Edit'}).click();
await modal.getByRole('button', {name: 'Actions'}).click();
await page.getByTestId('popover-content').getByRole('button', {name: 'Make owner'}).click();
const confirmation = page.getByTestId('confirmation-modal');
await confirmation.getByRole('button', {name: 'Yep — I\'m sure'}).click();
await expect(page.getByTestId('toast-success')).toHaveText(/Ownership transferred/);
await expect(section.getByTestId('owner-user')).toHaveText(/administrator@test\.com/);
expect(lastApiRequests.makeOwner?.body).toMatchObject({
owner: [{
id: administrator.id
}]
});
});
test('Limits un-suspending a user when there are too many users', async ({page}) => {
const userToEdit = responseFixtures.users.users.find(user => user.email === 'author@test.com')!;
await mockApi({page, requests: {
...globalDataRequests,
...limitRequests,
browseUsers: {method: 'GET', path: '/users/?limit=100&include=roles', response: {
users: [
...responseFixtures.users.users.filter(user => user.email !== 'author@test.com'),
{
...userToEdit,
status: 'inactive'
}
]
}},
browseConfig: {
...globalDataRequests.browseConfig,
response: {
config: {
...responseFixtures.config.config,
hostSettings: {
limits: {
staff: {
max: 1,
error: 'Your plan does not support more staff'
}
}
}
}
}
}
}});
await page.goto('/');
const section = page.getByTestId('users');
const activeTab = section.locator('[role=tabpanel]:not(.hidden)');
await section.getByRole('tab', {name: 'Authors'}).click();
const listItem = activeTab.getByTestId('user-list-item').last();
await listItem.hover();
await listItem.getByRole('button', {name: 'Edit'}).click();
const modal = page.getByTestId('user-detail-modal');
await expect(modal).toHaveText(/Suspended/);
await modal.getByRole('button', {name: 'Actions'}).click();
await page.getByTestId('popover-content').getByRole('button', {name: 'Un-suspend user'}).click();
await expect(page.getByTestId('limit-modal')).toHaveText(/Your plan does not support more staff/);
});
});