mirror of
https://github.com/hanzoai/team.git
synced 2026-09-30 01:57:35 +00:00
* Fix Manage Teams dropdown overflowing outside modal for last rows The role dropdown in the Admin Console Manage Teams modal always opened downward, so for users with many teams the menu for the last rows was pushed below the modal and out of view. Compute openUp for rows near the bottom of the list, mirroring the TeamMembersDropdown behavior. Co-authored-by: mattermost-code <[email protected]> * Render Manage Teams role dropdown via floating menu to fix overflow Migrate ManageTeamsDropdown from the deprecated Menu/MenuWrapper widget to the modern components/menu (MUI Popover). The old widget positioned the menu relative to the modal content, so for users with many teams the role dropdown on the last rows was pushed below the modal and off-screen. The new menu renders in a portal anchored to the trigger and opens upward for rows near the bottom of the list, mirroring TeamMembersDropdown. Co-authored-by: mattermost-code <[email protected]> * Add openUp helper coverage and action tests for ManageTeamsDropdown Extract the open-up positioning rule into a testable shouldOpenUp helper and cover its boundaries, plus the demote and error paths, so the fix for the dropdown overflow is exercised directly. Co-authored-by: mattermost-code <[email protected]> * Satisfy lint for table-driven test comment Co-authored-by: mattermost-code <[email protected]> * Gate onMemberChange assertions behind waitFor in dropdown tests Move onMemberChange expectations inside waitFor so they wait for the async updateTeamMemberSchemeRoles promise to resolve before asserting. Co-authored-by: mattermost-code <[email protected]> * Fix Manage Teams e2e to target MUI menu button and items The Manage Teams role dropdown was migrated from the deprecated components/widgets/menu (div.MenuWrapper) to the modern components/menu (MUI Popover). The Playwright spec still clicked div.MenuWrapper and looked for menu items inside the team row, but the new menu renders in a portal. Target the accessible role button and role menuitem elements instead. --------- Co-authored-by: mattermost-code <[email protected]> Co-authored-by: Hanzo Dev <[email protected]>
187 lines
6.9 KiB
TypeScript
187 lines
6.9 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import {type PlaywrightExtended, expect, test} from '@mattermost/playwright-lib';
|
|
|
|
test('MM-T5520-1 should activate and deactivate users', async ({pw}) => {
|
|
const {getUser, systemConsolePage} = await setupAndGetRandomUser(pw);
|
|
|
|
const userRow = systemConsolePage.users.usersTable.getRowByIndex(0);
|
|
|
|
// # Open menu and deactivate the user
|
|
const actionMenu = await userRow.openActionMenu();
|
|
await actionMenu.clickDeactivate();
|
|
|
|
// # Press confirm on the modal
|
|
await systemConsolePage.users.confirmModal.confirm();
|
|
|
|
// * Verify user is deactivated
|
|
await expect(userRow.container.getByText('Deactivated')).toBeVisible();
|
|
expect((await getUser()).delete_at).toBeGreaterThan(0);
|
|
|
|
// # Open menu and reactivate the user
|
|
const actionMenu2 = await userRow.openActionMenu();
|
|
await actionMenu2.clickActivate();
|
|
|
|
// * Verify user is activated
|
|
await expect(userRow.container.getByText('Member')).toBeVisible();
|
|
});
|
|
|
|
test('MM-T5520-2 should change user roles', async ({pw}) => {
|
|
const {getUser, systemConsolePage} = await setupAndGetRandomUser(pw);
|
|
|
|
const userRow = systemConsolePage.users.usersTable.getRowByIndex(0);
|
|
|
|
// # Open menu and click Manage roles
|
|
const actionMenu = await userRow.openActionMenu();
|
|
await actionMenu.clickManageRoles();
|
|
|
|
// # Change to System Admin and click Save
|
|
const systemAdmin = systemConsolePage.page.locator('input[name="systemadmin"]');
|
|
await systemAdmin.waitFor();
|
|
await systemAdmin.click();
|
|
await systemConsolePage.users.manageRolesModal.save();
|
|
|
|
// * Verify that the role was updated
|
|
await expect(userRow.container.getByText('System Admin')).toBeVisible();
|
|
expect((await getUser()).roles).toContain('system_admin');
|
|
|
|
// # Open menu and click Manage roles
|
|
const actionMenu2 = await userRow.openActionMenu();
|
|
await actionMenu2.clickManageRoles();
|
|
|
|
// # Change to Member and click Save
|
|
const systemMember = systemConsolePage.page.locator('input[name="systemmember"]');
|
|
await systemMember.waitFor();
|
|
await systemMember.click();
|
|
await systemConsolePage.users.manageRolesModal.save();
|
|
|
|
// * Verify that the role was updated
|
|
await expect(userRow.container.getByText('Member')).toBeVisible();
|
|
expect((await getUser()).roles).toContain('system_user');
|
|
});
|
|
|
|
test('MM-T5520-3 should be able to manage teams', async ({pw}) => {
|
|
const {systemConsolePage} = await setupAndGetRandomUser(pw);
|
|
const {page} = systemConsolePage;
|
|
|
|
const userRow = systemConsolePage.users.usersTable.getRowByIndex(0);
|
|
|
|
// # Open menu and click Manage teams
|
|
const actionMenu = await userRow.openActionMenu();
|
|
await actionMenu.clickManageTeams();
|
|
|
|
// The role dropdown renders its menu in a portal (MUI Popover), so the menu
|
|
// items live at the page level rather than inside the team row.
|
|
const team = page.locator('div.manage-teams__team');
|
|
|
|
// # Open the role dropdown and click Make Team Admin
|
|
await team.getByRole('button', {name: 'Team Member'}).click();
|
|
await page.getByRole('menuitem', {name: 'Make Team Admin'}).click();
|
|
|
|
// * Verify role is updated
|
|
await expect(team.getByText('Team Admin')).toBeVisible();
|
|
|
|
// # Change back to Team Member
|
|
await team.getByRole('button', {name: 'Team Admin'}).click();
|
|
await page.getByRole('menuitem', {name: 'Make Team Member'}).click();
|
|
|
|
// * Verify role is updated
|
|
await expect(team.getByText('Team Member')).toBeVisible();
|
|
|
|
// # Click Remove from Team
|
|
await team.getByRole('button', {name: 'Team Member'}).click();
|
|
await page.getByRole('menuitem', {name: 'Remove from Team'}).click();
|
|
|
|
// * The team should be detached
|
|
await team.waitFor({state: 'detached'});
|
|
await expect(team).not.toBeVisible();
|
|
});
|
|
|
|
test('MM-T5520-4 should reset the users password', async ({pw}) => {
|
|
const {systemConsolePage} = await setupAndGetRandomUser(pw);
|
|
|
|
const userRow = systemConsolePage.users.usersTable.getRowByIndex(0);
|
|
|
|
// # Open menu and click Reset Password
|
|
const actionMenu = await userRow.openActionMenu();
|
|
await actionMenu.clickResetPassword();
|
|
|
|
// # Enter a random password and click Reset
|
|
await systemConsolePage.users.resetPasswordModal.fillPassword(pw.newTestPassword());
|
|
await systemConsolePage.users.resetPasswordModal.reset();
|
|
});
|
|
|
|
test('MM-T5520-5 should change the users email', async ({pw}) => {
|
|
const {getUser, systemConsolePage} = await setupAndGetRandomUser(pw);
|
|
const newEmail = `${pw.random.id()}@example.com`;
|
|
|
|
const userRow = systemConsolePage.users.usersTable.getRowByIndex(0);
|
|
|
|
// # Open menu and click Update Email
|
|
const actionMenu = await userRow.openActionMenu();
|
|
await actionMenu.clickUpdateEmail();
|
|
|
|
// # Enter new email and click Update
|
|
await systemConsolePage.users.updateEmailModal.fillEmail(newEmail);
|
|
await systemConsolePage.users.updateEmailModal.update();
|
|
|
|
// * Verify that the email updated
|
|
await expect(userRow.container.getByText(newEmail)).toBeVisible();
|
|
expect((await getUser()).email).toEqual(newEmail);
|
|
});
|
|
|
|
test('MM-T5520-6 should revoke sessions', async ({pw}) => {
|
|
const {systemConsolePage} = await setupAndGetRandomUser(pw);
|
|
|
|
const userRow = systemConsolePage.users.usersTable.getRowByIndex(0);
|
|
|
|
// # Open menu and revoke sessions
|
|
const actionMenu = await userRow.openActionMenu();
|
|
await actionMenu.clickRevokeSessions();
|
|
|
|
// # Press confirm on the modal
|
|
await systemConsolePage.users.confirmModal.confirm();
|
|
|
|
// * Verify no error is displayed
|
|
await expect(userRow.container.locator('.error')).not.toBeVisible();
|
|
});
|
|
|
|
/**
|
|
* Setup a new random user, and search for it such that it's the first row in the list
|
|
* @param pw
|
|
* @returns A function to get the refreshed user, and the System Console page for navigation
|
|
*/
|
|
async function setupAndGetRandomUser(pw: PlaywrightExtended) {
|
|
const {adminUser, adminClient} = await pw.initSetup();
|
|
|
|
if (!adminUser) {
|
|
throw new Error('Failed to create admin user');
|
|
}
|
|
|
|
// # Log in as admin
|
|
const {systemConsolePage} = await pw.testBrowser.login(adminUser);
|
|
|
|
// # Create a random user to edit
|
|
const user = await adminClient.createUser(await pw.random.user(), '', '');
|
|
const team = await adminClient.createTeam(await pw.random.team());
|
|
await adminClient.addToTeam(team.id, user.id);
|
|
|
|
// # Visit system console
|
|
await systemConsolePage.goto();
|
|
await systemConsolePage.toBeVisible();
|
|
|
|
// # Go to Users section
|
|
await systemConsolePage.sidebar.users.click();
|
|
await systemConsolePage.users.toBeVisible();
|
|
|
|
// # Search for the user
|
|
await systemConsolePage.users.searchUsers(user.email);
|
|
|
|
// Wait for search results
|
|
const userRow = systemConsolePage.users.usersTable.getRowByIndex(0);
|
|
await expect(userRow.container.getByText(user.email)).toBeVisible();
|
|
|
|
return {getUser: () => adminClient.getUser(user.id), systemConsolePage};
|
|
}
|