mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
End to End test for Admin Reporting for Users, new User Management screen (#26077)
https://mattermost.atlassian.net/browse/MM-56672 https://mattermost.atlassian.net/browse/MM-56666 https://mattermost.atlassian.net/browse/MM-56673
This commit is contained in:
parent
4c8a134659
commit
90b21cad33
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {expect, Locator, Page} from '@playwright/test';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the generic confirm modal that is used in the app.
|
||||||
|
* It has optional cancel button, optional checkbox and confirm button along with title and message body.
|
||||||
|
* It can present in different parts of the app such as channel, system console, etc and hence its constructor
|
||||||
|
* should be able to accept the page object of the app and an optional id to uniquely identify the modal.
|
||||||
|
*/
|
||||||
|
export default class GenericConfirmModal {
|
||||||
|
readonly container: Locator;
|
||||||
|
|
||||||
|
readonly confirmButton: Locator;
|
||||||
|
readonly cancelButton: Locator;
|
||||||
|
|
||||||
|
constructor(page: Page, id?: string) {
|
||||||
|
const modalId = `#confirmModal ${id}`.trim();
|
||||||
|
this.container = page.locator(modalId);
|
||||||
|
this.confirmButton = page.locator('#confirmModalButton');
|
||||||
|
this.cancelButton = page.locator('#cancelModalButton');
|
||||||
|
}
|
||||||
|
|
||||||
|
async toBeVisible() {
|
||||||
|
await expect(this.container).toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
async confirm() {
|
||||||
|
await this.confirmButton.waitFor();
|
||||||
|
await this.confirmButton.click();
|
||||||
|
|
||||||
|
// Wait for the modal to disappear
|
||||||
|
await expect(this.container).not.toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
async cancel() {
|
||||||
|
await this.cancelButton.waitFor();
|
||||||
|
await this.cancelButton.click();
|
||||||
|
|
||||||
|
// Wait for the modal to disappear
|
||||||
|
await expect(this.container).not.toBeVisible();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {GenericConfirmModal};
|
@ -19,6 +19,15 @@ import {PostReminderMenu} from './channels/post_reminder_menu';
|
|||||||
import {PostMenu} from './channels/post_menu';
|
import {PostMenu} from './channels/post_menu';
|
||||||
import {ThreadFooter} from './channels/thread_footer';
|
import {ThreadFooter} from './channels/thread_footer';
|
||||||
import {EmojiGifPicker} from './channels/emoji_gif_picker';
|
import {EmojiGifPicker} from './channels/emoji_gif_picker';
|
||||||
|
import {GenericConfirmModal} from './channels/generic_confirm_modal';
|
||||||
|
|
||||||
|
import {SystemConsoleSidebar} from './system_console/sidebar';
|
||||||
|
import {SystemConsoleNavbar} from './system_console/navbar';
|
||||||
|
|
||||||
|
import {SystemUsers} from './system_console/sections/system_users/system_users';
|
||||||
|
import {SystemUsersFilterPopover} from './system_console/sections/system_users/filter_popover';
|
||||||
|
import {SystemUsersFilterMenu} from './system_console/sections/system_users/filter_menu';
|
||||||
|
import {SystemUsersColumnToggleMenu} from './system_console/sections/system_users/column_toggle_menu';
|
||||||
|
|
||||||
const components = {
|
const components = {
|
||||||
GlobalHeader,
|
GlobalHeader,
|
||||||
@ -39,6 +48,13 @@ const components = {
|
|||||||
MainHeader,
|
MainHeader,
|
||||||
PostReminderMenu,
|
PostReminderMenu,
|
||||||
EmojiGifPicker,
|
EmojiGifPicker,
|
||||||
|
GenericConfirmModal,
|
||||||
|
SystemConsoleSidebar,
|
||||||
|
SystemConsoleNavbar,
|
||||||
|
SystemUsers,
|
||||||
|
SystemUsersFilterPopover,
|
||||||
|
SystemUsersFilterMenu,
|
||||||
|
SystemUsersColumnToggleMenu,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {expect, Locator} from '@playwright/test';
|
||||||
|
|
||||||
|
export default class SystemConsoleNavbar {
|
||||||
|
readonly container: Locator;
|
||||||
|
|
||||||
|
constructor(container: Locator) {
|
||||||
|
this.container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
async toBeVisible() {
|
||||||
|
await expect(this.container).toBeVisible();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {SystemConsoleNavbar};
|
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {expect, Locator} from '@playwright/test';
|
||||||
|
|
||||||
|
class SystemUsersColumnToggleMenu {
|
||||||
|
readonly container: Locator;
|
||||||
|
|
||||||
|
constructor(container: Locator) {
|
||||||
|
this.container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
async toBeVisible() {
|
||||||
|
await expect(this.container).toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the locator for the menu item with the given name.
|
||||||
|
*/
|
||||||
|
async getMenuItem(menuItem: string) {
|
||||||
|
const menuItemLocator = this.container.getByRole('menuitemcheckbox').filter({hasText: menuItem});
|
||||||
|
await menuItemLocator.waitFor();
|
||||||
|
|
||||||
|
return menuItemLocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of locators for all the menu items.
|
||||||
|
*/
|
||||||
|
async getAllMenuItems() {
|
||||||
|
const menuItemLocators = this.container.getByRole('menuitemcheckbox');
|
||||||
|
return menuItemLocators;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass in the item name to check/uncheck the menu item.
|
||||||
|
*/
|
||||||
|
async clickMenuItem(menuItem: string) {
|
||||||
|
const menuItemLocator = await this.getMenuItem(menuItem);
|
||||||
|
await menuItemLocator.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close column toggle menu.
|
||||||
|
*/
|
||||||
|
async close() {
|
||||||
|
await this.container.press('Escape');
|
||||||
|
await expect(this.container).not.toBeVisible();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {SystemUsersColumnToggleMenu};
|
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {expect, Locator} from '@playwright/test';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The dropdown menu which appears for both Role and Status filter.
|
||||||
|
*/
|
||||||
|
class SystemUsersFilterMenu {
|
||||||
|
readonly container: Locator;
|
||||||
|
|
||||||
|
constructor(container: Locator) {
|
||||||
|
this.container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
async toBeVisible() {
|
||||||
|
await expect(this.container).toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the locator for the menu item with the given name.
|
||||||
|
*/
|
||||||
|
async getMenuItem(menuItem: string) {
|
||||||
|
const menuItemLocator = this.container.getByText(menuItem);
|
||||||
|
await menuItemLocator.waitFor();
|
||||||
|
|
||||||
|
return menuItemLocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clicks on the menu item with the given name.
|
||||||
|
*/
|
||||||
|
async clickMenuItem(menuItem: string) {
|
||||||
|
const menuItemLocator = await this.getMenuItem(menuItem);
|
||||||
|
await menuItemLocator.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the menu.
|
||||||
|
*/
|
||||||
|
async close() {
|
||||||
|
await this.container.press('Escape');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {SystemUsersFilterMenu};
|
@ -0,0 +1,70 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {expect, Locator} from '@playwright/test';
|
||||||
|
|
||||||
|
class SystemUsersFilterPopover {
|
||||||
|
readonly container: Locator;
|
||||||
|
|
||||||
|
readonly teamMenuInput: Locator;
|
||||||
|
readonly roleMenuButton: Locator;
|
||||||
|
readonly statusMenuButton: Locator;
|
||||||
|
|
||||||
|
readonly applyButton: Locator;
|
||||||
|
|
||||||
|
constructor(container: Locator) {
|
||||||
|
this.container = container;
|
||||||
|
|
||||||
|
this.teamMenuInput = this.container.locator('#asyncTeamSelectInput');
|
||||||
|
this.roleMenuButton = this.container.locator('#DropdownInput_filterRole');
|
||||||
|
this.statusMenuButton = this.container.locator('#DropdownInput_filterStatus');
|
||||||
|
|
||||||
|
this.applyButton = this.container.getByText('Apply');
|
||||||
|
}
|
||||||
|
|
||||||
|
async toBeVisible() {
|
||||||
|
await expect(this.container).toBeVisible();
|
||||||
|
await expect(this.applyButton).toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the filter settings.
|
||||||
|
*/
|
||||||
|
async save() {
|
||||||
|
await this.applyButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to type in the team filter for searching.
|
||||||
|
*/
|
||||||
|
async searchInTeamMenu(teamDisplayName: string) {
|
||||||
|
expect(this.teamMenuInput).toBeVisible();
|
||||||
|
await this.teamMenuInput.fill(teamDisplayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the role filter menu.
|
||||||
|
*/
|
||||||
|
async openRoleMenu() {
|
||||||
|
expect(this.roleMenuButton).toBeVisible();
|
||||||
|
await this.roleMenuButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the status filter menu.
|
||||||
|
*/
|
||||||
|
async openStatusMenu() {
|
||||||
|
expect(this.statusMenuButton).toBeVisible();
|
||||||
|
await this.statusMenuButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the filter popover.
|
||||||
|
*/
|
||||||
|
async close() {
|
||||||
|
await this.container.press('Escape');
|
||||||
|
await expect(this.container).not.toBeVisible();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {SystemUsersFilterPopover};
|
@ -0,0 +1,132 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {expect, Locator} from '@playwright/test';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System Console -> User Management -> Users
|
||||||
|
*/
|
||||||
|
export default class SystemUsers {
|
||||||
|
readonly container: Locator;
|
||||||
|
|
||||||
|
readonly searchInput: Locator;
|
||||||
|
readonly columnToggleMenuButton: Locator;
|
||||||
|
readonly dateRangeSelectorMenuButton: Locator;
|
||||||
|
readonly exportButton: Locator;
|
||||||
|
readonly filterPopoverButton: Locator;
|
||||||
|
readonly actionMenuButtons: Locator[];
|
||||||
|
|
||||||
|
readonly loadingSpinner: Locator;
|
||||||
|
|
||||||
|
constructor(container: Locator) {
|
||||||
|
this.container = container;
|
||||||
|
|
||||||
|
this.searchInput = this.container.getByLabel('Search users');
|
||||||
|
this.columnToggleMenuButton = this.container.locator('#systemUsersColumnTogglerMenuButton');
|
||||||
|
this.dateRangeSelectorMenuButton = this.container.locator('#systemUsersDateRangeSelectorMenuButton');
|
||||||
|
this.exportButton = this.container.getByText('Export');
|
||||||
|
this.filterPopoverButton = this.container.getByText(/Filters \(\d+\)/);
|
||||||
|
this.actionMenuButtons = Array.from(Array(10).keys()).map((index) =>
|
||||||
|
this.container.locator(`#actionMenuButton-systemUsersTable-${index}`),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.loadingSpinner = this.container.getByText('Loading');
|
||||||
|
}
|
||||||
|
|
||||||
|
async toBeVisible() {
|
||||||
|
await expect(this.container).toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
async isLoadingComplete() {
|
||||||
|
await expect(this.loadingSpinner).toHaveCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the locator for the header of the given column.
|
||||||
|
*/
|
||||||
|
async getColumnHeader(columnName: string) {
|
||||||
|
const columnHeader = this.container.getByRole('columnheader').filter({hasText: columnName});
|
||||||
|
return columnHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if given column exists in the table. By searching for the column header.
|
||||||
|
*/
|
||||||
|
async doesColumnExist(columnName: string) {
|
||||||
|
const columnHeader = await this.getColumnHeader(columnName);
|
||||||
|
return await columnHeader.isVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clicks on the column header of the given column for sorting.
|
||||||
|
*/
|
||||||
|
async clickSortOnColumn(columnName: string) {
|
||||||
|
const columnHeader = await this.getColumnHeader(columnName);
|
||||||
|
await columnHeader.waitFor();
|
||||||
|
await columnHeader.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the locator for the given row number. If '0' is passed, it will return the header row.
|
||||||
|
*/
|
||||||
|
async getNthRow(rowNumber: number) {
|
||||||
|
const row = this.container.getByRole('row').nth(rowNumber);
|
||||||
|
await row.waitFor();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the Filter popover
|
||||||
|
*/
|
||||||
|
async openFilterPopover() {
|
||||||
|
expect(this.filterPopoverButton).toBeVisible();
|
||||||
|
await this.filterPopoverButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the column toggle menu
|
||||||
|
*/
|
||||||
|
async openColumnToggleMenu() {
|
||||||
|
expect(this.columnToggleMenuButton).toBeVisible();
|
||||||
|
await this.columnToggleMenuButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the date range selector menu
|
||||||
|
*/
|
||||||
|
async openDateRangeSelectorMenu() {
|
||||||
|
expect(this.dateRangeSelectorMenuButton).toBeVisible();
|
||||||
|
await this.dateRangeSelectorMenuButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enter the given search term in the search input
|
||||||
|
*/
|
||||||
|
async enterSearchText(searchText: string) {
|
||||||
|
expect(this.searchInput).toBeVisible();
|
||||||
|
await this.searchInput.fill(`${searchText}`);
|
||||||
|
|
||||||
|
await this.isLoadingComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches and verifies that the row with given text is found
|
||||||
|
*/
|
||||||
|
async verifyRowWithTextIsFound(text: string) {
|
||||||
|
const foundUser = this.container.getByText(text);
|
||||||
|
await foundUser.waitFor();
|
||||||
|
|
||||||
|
await expect(foundUser).toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches and verifies that the row with given text is not found
|
||||||
|
*/
|
||||||
|
async verifyRowWithTextIsNotFound(text: string) {
|
||||||
|
const foundUser = this.container.getByText(text);
|
||||||
|
await expect(foundUser).not.toBeVisible();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {SystemUsers};
|
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {expect, Locator} from '@playwright/test';
|
||||||
|
|
||||||
|
export default class SystemConsoleSidebar {
|
||||||
|
readonly container: Locator;
|
||||||
|
|
||||||
|
readonly searchInput: Locator;
|
||||||
|
|
||||||
|
constructor(container: Locator) {
|
||||||
|
this.container = container;
|
||||||
|
|
||||||
|
this.searchInput = container.getByPlaceholder('Find settings');
|
||||||
|
}
|
||||||
|
|
||||||
|
async toBeVisible() {
|
||||||
|
await expect(this.container).toBeVisible();
|
||||||
|
await expect(this.searchInput).toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clicks on the sidebar section link with the given name. Pass the exact name of the section.
|
||||||
|
* @param sectionName
|
||||||
|
*/
|
||||||
|
async goToItem(sectionName: string) {
|
||||||
|
const section = this.container.getByText(sectionName, {exact: true});
|
||||||
|
await section.waitFor();
|
||||||
|
await section.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for the given item in the sidebar search input.
|
||||||
|
* @param itemName
|
||||||
|
*/
|
||||||
|
async searchForItem(itemName: string) {
|
||||||
|
await this.searchInput.fill(itemName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {SystemConsoleSidebar};
|
@ -6,6 +6,7 @@ import {LandingLoginPage} from './landing_login';
|
|||||||
import {LoginPage} from './login';
|
import {LoginPage} from './login';
|
||||||
import {ResetPasswordPage} from './reset_password';
|
import {ResetPasswordPage} from './reset_password';
|
||||||
import {SignupPage} from './signup';
|
import {SignupPage} from './signup';
|
||||||
|
import {SystemConsolePage} from './system_console';
|
||||||
|
|
||||||
const pages = {
|
const pages = {
|
||||||
ChannelsPage,
|
ChannelsPage,
|
||||||
@ -13,6 +14,7 @@ const pages = {
|
|||||||
LoginPage,
|
LoginPage,
|
||||||
ResetPasswordPage,
|
ResetPasswordPage,
|
||||||
SignupPage,
|
SignupPage,
|
||||||
|
SystemConsolePage,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {pages, ChannelsPage, LandingLoginPage, LoginPage, SignupPage};
|
export {pages, ChannelsPage, LandingLoginPage, LoginPage, SignupPage};
|
||||||
|
63
e2e-tests/playwright/support/ui/pages/system_console.ts
Normal file
63
e2e-tests/playwright/support/ui/pages/system_console.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {Page} from '@playwright/test';
|
||||||
|
import {components} from '../components';
|
||||||
|
|
||||||
|
class SystemConsolePage {
|
||||||
|
readonly page: Page;
|
||||||
|
|
||||||
|
readonly sidebar;
|
||||||
|
readonly navbar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System Console -> User Management -> Users
|
||||||
|
*/
|
||||||
|
readonly systemUsers;
|
||||||
|
readonly systemUsersFilterPopover;
|
||||||
|
readonly systemUsersRoleMenu;
|
||||||
|
readonly systemUsersStatusMenu;
|
||||||
|
readonly systemUsersDateRangeMenu;
|
||||||
|
readonly systemUsersColumnToggleMenu;
|
||||||
|
readonly systemUsersActionMenus;
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
this.page = page;
|
||||||
|
|
||||||
|
// Areas of the page
|
||||||
|
this.navbar = new components.SystemConsoleNavbar(page.locator('.backstage-navbar'));
|
||||||
|
this.sidebar = new components.SystemConsoleSidebar(page.locator('.admin-sidebar'));
|
||||||
|
|
||||||
|
// Sections and sub-sections
|
||||||
|
this.systemUsers = new components.SystemUsers(page.getByTestId('systemUsersSection'));
|
||||||
|
|
||||||
|
// Menus & Popovers
|
||||||
|
this.systemUsersFilterPopover = new components.SystemUsersFilterPopover(
|
||||||
|
page.locator('#systemUsersFilterPopover'),
|
||||||
|
);
|
||||||
|
this.systemUsersRoleMenu = new components.SystemUsersFilterMenu(page.locator('#DropdownInput_filterRole'));
|
||||||
|
this.systemUsersStatusMenu = new components.SystemUsersFilterMenu(page.locator('#DropdownInput_filterStatus'));
|
||||||
|
this.systemUsersColumnToggleMenu = new components.SystemUsersColumnToggleMenu(
|
||||||
|
page.locator('#systemUsersColumnTogglerMenu'),
|
||||||
|
);
|
||||||
|
this.systemUsersDateRangeMenu = new components.SystemUsersFilterMenu(
|
||||||
|
page.locator('#systemUsersDateRangeSelectorMenu'),
|
||||||
|
);
|
||||||
|
this.systemUsersActionMenus = Array.from(Array(10).keys()).map(
|
||||||
|
(index) => new components.SystemUsersFilterMenu(page.locator(`#actionMenu-systemUsersTable-${index}`)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async toBeVisible() {
|
||||||
|
await this.page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
|
await this.sidebar.toBeVisible();
|
||||||
|
await this.navbar.toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
async goto() {
|
||||||
|
await this.page.goto('/admin_console');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {SystemConsolePage};
|
@ -45,3 +45,4 @@ export function getRandomId(length = 7): string {
|
|||||||
export const defaultTeam = {name: 'ad-1', displayName: 'eligendi', type: 'O'};
|
export const defaultTeam = {name: 'ad-1', displayName: 'eligendi', type: 'O'};
|
||||||
|
|
||||||
export const illegalRe = /[/?<>\\:*|":&();]/g;
|
export const illegalRe = /[/?<>\\:*|":&();]/g;
|
||||||
|
export const simpleEmailRe = /\S+@\S+\.\S+/;
|
||||||
|
@ -0,0 +1,214 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {TestBrowser} from '@e2e-support//browser_context';
|
||||||
|
import {Client, createRandomTeam, createRandomUser} from '@e2e-support/server';
|
||||||
|
import {expect, test} from '@e2e-support/test_fixture';
|
||||||
|
import {components} from '@e2e-support/ui/components';
|
||||||
|
import {SystemConsolePage} from '@e2e-support/ui/pages/system_console';
|
||||||
|
import {getRandomId} from '@e2e-support/util';
|
||||||
|
import {UserProfile} from '@mattermost/types/users';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup a new random user, and search for it such that it's the first row in the list
|
||||||
|
* @param pw
|
||||||
|
* @param pages
|
||||||
|
* @returns A function to get the refreshed user, and the System Console page for navigation
|
||||||
|
*/
|
||||||
|
async function setupAndGetRandomUser(
|
||||||
|
pw: {testBrowser: TestBrowser; initSetup: () => Promise<{adminUser: UserProfile | null; adminClient: Client}>},
|
||||||
|
pages: {SystemConsolePage: typeof SystemConsolePage},
|
||||||
|
) {
|
||||||
|
const {adminUser, adminClient} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Create a random user to edit for
|
||||||
|
const user = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
const team = await adminClient.createTeam(createRandomTeam());
|
||||||
|
await adminClient.addToTeam(team.id, user.id);
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// # Search for user-1
|
||||||
|
await systemConsolePage.systemUsers.enterSearchText(user.email);
|
||||||
|
const userRow = await systemConsolePage.systemUsers.getNthRow(1);
|
||||||
|
await userRow.getByText(user.email).waitFor();
|
||||||
|
const innerText = await userRow.innerText();
|
||||||
|
expect(innerText).toContain(user.email);
|
||||||
|
|
||||||
|
return {getUser: () => adminClient.getUser(user.id), systemConsolePage};
|
||||||
|
}
|
||||||
|
|
||||||
|
test('MM-T5520-1 should activate and deactivate users', async ({pw, pages}) => {
|
||||||
|
const {getUser, systemConsolePage} = await setupAndGetRandomUser(pw, pages);
|
||||||
|
|
||||||
|
// # Open menu and deactivate the user
|
||||||
|
await systemConsolePage.systemUsers.actionMenuButtons[0].click();
|
||||||
|
const deactivate = await systemConsolePage.systemUsersActionMenus[0].getMenuItem('Deactivate');
|
||||||
|
await deactivate.click();
|
||||||
|
|
||||||
|
// # Press confirm on the modal
|
||||||
|
const confirmModal = new components.GenericConfirmModal(systemConsolePage.page);
|
||||||
|
await confirmModal.confirm();
|
||||||
|
|
||||||
|
// * Verify user is deactivated
|
||||||
|
const firstRow = await systemConsolePage.systemUsers.getNthRow(1);
|
||||||
|
await firstRow.getByText('Deactivated').waitFor();
|
||||||
|
expect(await firstRow.innerText()).toContain('Deactivated');
|
||||||
|
expect((await getUser()).delete_at).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
// # Open menu and reactivate the user
|
||||||
|
await systemConsolePage.systemUsers.actionMenuButtons[0].click();
|
||||||
|
const activate = await systemConsolePage.systemUsersActionMenus[0].getMenuItem('Activate');
|
||||||
|
await activate.click();
|
||||||
|
|
||||||
|
// * Verify user is activated
|
||||||
|
await firstRow.getByText('Member').waitFor();
|
||||||
|
expect(await firstRow.innerText()).toContain('Member');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5520-2 should change user roles', async ({pw, pages}) => {
|
||||||
|
const {getUser, systemConsolePage} = await setupAndGetRandomUser(pw, pages);
|
||||||
|
|
||||||
|
// # Open menu and click Manage roles
|
||||||
|
await systemConsolePage.systemUsers.actionMenuButtons[0].click();
|
||||||
|
let manageRoles = await systemConsolePage.systemUsersActionMenus[0].getMenuItem('Manage roles');
|
||||||
|
await manageRoles.click();
|
||||||
|
|
||||||
|
// # Change to System Admin and click Save
|
||||||
|
const systemAdmin = systemConsolePage.page.locator('input[name="systemadmin"]');
|
||||||
|
await systemAdmin.waitFor();
|
||||||
|
await systemAdmin.click();
|
||||||
|
await systemConsolePage.page.locator('button.btn-primary').click();
|
||||||
|
|
||||||
|
// * Verify that the modal closed and no error showed
|
||||||
|
await systemAdmin.waitFor({state: 'detached'});
|
||||||
|
|
||||||
|
// * Verify that the role was updated
|
||||||
|
const firstRow = await systemConsolePage.systemUsers.getNthRow(1);
|
||||||
|
expect(await firstRow.innerText()).toContain('System Admin');
|
||||||
|
expect((await getUser()).roles).toContain('system_admin');
|
||||||
|
|
||||||
|
// # Open menu and click Manage roles
|
||||||
|
await systemConsolePage.systemUsers.actionMenuButtons[0].click();
|
||||||
|
manageRoles = await systemConsolePage.systemUsersActionMenus[0].getMenuItem('Manage roles');
|
||||||
|
await manageRoles.click();
|
||||||
|
|
||||||
|
// # Change to Member and click Save
|
||||||
|
const systemMember = systemConsolePage.page.locator('input[name="systemmember"]');
|
||||||
|
await systemMember.waitFor();
|
||||||
|
await systemMember.click();
|
||||||
|
await systemConsolePage.page.locator('button.btn-primary').click();
|
||||||
|
|
||||||
|
// * Verify that the modal closed and no error showed
|
||||||
|
await systemMember.waitFor({state: 'detached'});
|
||||||
|
|
||||||
|
// * Verify that the role was updated
|
||||||
|
expect(await firstRow.innerText()).toContain('Member');
|
||||||
|
expect((await getUser()).roles).toContain('system_user');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5520-3 should be able to manage teams', async ({pw, pages}) => {
|
||||||
|
const {systemConsolePage} = await setupAndGetRandomUser(pw, pages);
|
||||||
|
|
||||||
|
// # Open menu and click Manage teams
|
||||||
|
await systemConsolePage.systemUsers.actionMenuButtons[0].click();
|
||||||
|
const manageTeams = await systemConsolePage.systemUsersActionMenus[0].getMenuItem('Manage teams');
|
||||||
|
await manageTeams.click();
|
||||||
|
|
||||||
|
// # Click Make Team Admin
|
||||||
|
const team = systemConsolePage.page.locator('div.manage-teams__team');
|
||||||
|
const teamDropdown = team.locator('div.MenuWrapper');
|
||||||
|
await teamDropdown.click();
|
||||||
|
const makeTeamAdmin = teamDropdown.getByText('Make Team Admin');
|
||||||
|
await makeTeamAdmin.click();
|
||||||
|
|
||||||
|
// * Verify role is updated
|
||||||
|
expect(await team.innerText()).toContain('Team Admin');
|
||||||
|
|
||||||
|
// # Change back to Team Member
|
||||||
|
await teamDropdown.click();
|
||||||
|
const makeTeamMember = teamDropdown.getByText('Make Team Member');
|
||||||
|
await makeTeamMember.click();
|
||||||
|
|
||||||
|
// * Verify role is updated
|
||||||
|
expect(await team.innerText()).toContain('Team Member');
|
||||||
|
|
||||||
|
// # Click Remove From Team
|
||||||
|
await teamDropdown.click();
|
||||||
|
const removeFromTeam = teamDropdown.getByText('Remove From Team');
|
||||||
|
await removeFromTeam.click();
|
||||||
|
|
||||||
|
// * The team should be detached
|
||||||
|
await team.waitFor({state: 'detached'});
|
||||||
|
expect(team).not.toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5520-4 should reset the users password', async ({pw, pages}) => {
|
||||||
|
const {systemConsolePage} = await setupAndGetRandomUser(pw, pages);
|
||||||
|
|
||||||
|
// # Open menu and click Reset Password
|
||||||
|
await systemConsolePage.systemUsers.actionMenuButtons[0].click();
|
||||||
|
const resetPassword = await systemConsolePage.systemUsersActionMenus[0].getMenuItem('Reset password');
|
||||||
|
await resetPassword.click();
|
||||||
|
|
||||||
|
// # Enter a random password and click Save
|
||||||
|
const passwordInput = systemConsolePage.page.locator('input[type="password"]');
|
||||||
|
await passwordInput.fill(getRandomId());
|
||||||
|
await systemConsolePage.page.locator('button.btn-primary').click();
|
||||||
|
|
||||||
|
// * Verify that the modal closed and no error showed
|
||||||
|
await passwordInput.waitFor({state: 'detached'});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5520-5 should change the users email', async ({pw, pages}) => {
|
||||||
|
const {getUser, systemConsolePage} = await setupAndGetRandomUser(pw, pages);
|
||||||
|
const newEmail = `${getRandomId()}@example.com`;
|
||||||
|
|
||||||
|
// # Open menu and click Update Email
|
||||||
|
await systemConsolePage.systemUsers.actionMenuButtons[0].click();
|
||||||
|
const updateEmail = await systemConsolePage.systemUsersActionMenus[0].getMenuItem('Update email');
|
||||||
|
await updateEmail.click();
|
||||||
|
|
||||||
|
// # Enter a random password and click Save
|
||||||
|
const emailInput = await systemConsolePage.page.locator('input[type="email"]');
|
||||||
|
await emailInput.fill(newEmail);
|
||||||
|
await systemConsolePage.page.locator('button.btn-primary').click();
|
||||||
|
|
||||||
|
// * Verify that the modal closed
|
||||||
|
await emailInput.waitFor({state: 'detached'});
|
||||||
|
|
||||||
|
// * Verify that the email updated
|
||||||
|
const firstRow = await systemConsolePage.systemUsers.getNthRow(1);
|
||||||
|
expect(await firstRow.innerText()).toContain(newEmail);
|
||||||
|
expect((await getUser()).email).toEqual(newEmail);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5520-6 should revoke sessions', async ({pw, pages}) => {
|
||||||
|
const {systemConsolePage} = await setupAndGetRandomUser(pw, pages);
|
||||||
|
|
||||||
|
// # Open menu and revoke sessions
|
||||||
|
await systemConsolePage.systemUsers.actionMenuButtons[0].click();
|
||||||
|
const removeSessions = await systemConsolePage.systemUsersActionMenus[0].getMenuItem('Remove sessions');
|
||||||
|
await removeSessions.click();
|
||||||
|
|
||||||
|
// # Press confirm on the modal
|
||||||
|
const confirmModal = new components.GenericConfirmModal(systemConsolePage.page);
|
||||||
|
await confirmModal.confirm();
|
||||||
|
|
||||||
|
const firstRow = await systemConsolePage.systemUsers.getNthRow(1);
|
||||||
|
expect(await firstRow.innerHTML()).not.toContain('class="error"');
|
||||||
|
});
|
@ -0,0 +1,97 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {expect} from '@playwright/test';
|
||||||
|
|
||||||
|
import {test} from '@e2e-support/test_fixture';
|
||||||
|
import {createRandomUser} from '@e2e-support/server';
|
||||||
|
import {simpleEmailRe} from '@e2e-support/util';
|
||||||
|
|
||||||
|
test('MM-T5523-1 Sortable columns should sort the list when clicked', async ({pw, pages}) => {
|
||||||
|
const {adminUser, adminClient} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Create 10 random users
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// * Verify that 'Email' column has aria-sort attribute
|
||||||
|
const userDetailsColumnHeader = await systemConsolePage.systemUsers.getColumnHeader('Email');
|
||||||
|
expect(await userDetailsColumnHeader.isVisible()).toBe(true);
|
||||||
|
expect(userDetailsColumnHeader).toHaveAttribute('aria-sort');
|
||||||
|
|
||||||
|
// # Store the first row's email before sorting
|
||||||
|
const firstRowWithoutSort = await systemConsolePage.systemUsers.getNthRow(1);
|
||||||
|
const firstRowEmailWithoutSort = await firstRowWithoutSort.getByText(simpleEmailRe).allInnerTexts();
|
||||||
|
|
||||||
|
// # Click on the 'Email' column header to sort
|
||||||
|
await systemConsolePage.systemUsers.clickSortOnColumn('Email');
|
||||||
|
await systemConsolePage.systemUsers.isLoadingComplete();
|
||||||
|
|
||||||
|
// # Store the first row's email after sorting
|
||||||
|
const firstRowWithSort = await systemConsolePage.systemUsers.getNthRow(1);
|
||||||
|
const firstRowEmailWithSort = await firstRowWithSort.getByText(simpleEmailRe).allInnerTexts();
|
||||||
|
|
||||||
|
// * Verify that the first row is now different
|
||||||
|
expect(firstRowEmailWithoutSort).not.toBe(firstRowEmailWithSort);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5523-2 Non sortable columns should not sort the list when clicked', async ({pw, pages}) => {
|
||||||
|
const {adminUser, adminClient} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Create 10 random users
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// * Verify that 'Last login' column does not have aria-sort attribute
|
||||||
|
const userDetailsColumnHeader = await systemConsolePage.systemUsers.getColumnHeader('Last login');
|
||||||
|
expect(await userDetailsColumnHeader.isVisible()).toBe(true);
|
||||||
|
expect(userDetailsColumnHeader).not.toHaveAttribute('aria-sort');
|
||||||
|
|
||||||
|
// # Store the first row's email without sorting
|
||||||
|
const firstRowWithoutSort = await systemConsolePage.systemUsers.getNthRow(1);
|
||||||
|
const firstRowEmailWithoutSort = await firstRowWithoutSort.getByText(simpleEmailRe).allInnerTexts();
|
||||||
|
|
||||||
|
// # Try to click on the 'Last login' column header to sort
|
||||||
|
await systemConsolePage.systemUsers.clickSortOnColumn('Last login');
|
||||||
|
|
||||||
|
// # Store the first row's email after sorting
|
||||||
|
const firstRowWithSort = await systemConsolePage.systemUsers.getNthRow(1);
|
||||||
|
const firstRowEmailWithSort = await firstRowWithSort.getByText(simpleEmailRe).allInnerTexts();
|
||||||
|
|
||||||
|
// * Verify that the first row's email is still the same
|
||||||
|
expect(firstRowEmailWithoutSort).toEqual(firstRowEmailWithSort);
|
||||||
|
});
|
@ -0,0 +1,134 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {expect} from '@playwright/test';
|
||||||
|
|
||||||
|
import {test} from '@e2e-support/test_fixture';
|
||||||
|
|
||||||
|
test('MM-T5523-3 Should list the column names with checkboxes in the correct order', async ({pw, pages}) => {
|
||||||
|
const {adminUser} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// # Open the column toggle menu
|
||||||
|
await systemConsolePage.systemUsers.openColumnToggleMenu();
|
||||||
|
await systemConsolePage.systemUsersColumnToggleMenu.toBeVisible();
|
||||||
|
|
||||||
|
// # Get all the menu items
|
||||||
|
const menuItems = await systemConsolePage.systemUsersColumnToggleMenu.getAllMenuItems();
|
||||||
|
const menuItemsTexts = await menuItems.allInnerTexts();
|
||||||
|
|
||||||
|
// * Verify menu items exists in the correct order
|
||||||
|
expect(menuItemsTexts).toHaveLength(9);
|
||||||
|
expect(menuItemsTexts).toEqual([
|
||||||
|
'User details',
|
||||||
|
'Email',
|
||||||
|
'Member since',
|
||||||
|
'Last login',
|
||||||
|
'Last activity',
|
||||||
|
'Last post',
|
||||||
|
'Days active',
|
||||||
|
'Messages posted',
|
||||||
|
'Actions',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5523-4 Should allow certain columns to be checked and others to be disabled', async ({pw, pages}) => {
|
||||||
|
const {adminUser} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// # Open the column toggle menu
|
||||||
|
await systemConsolePage.systemUsers.openColumnToggleMenu();
|
||||||
|
await systemConsolePage.systemUsersColumnToggleMenu.toBeVisible();
|
||||||
|
|
||||||
|
// * Verify that 'Display Name' is disabled
|
||||||
|
const displayNameMenuItem = await systemConsolePage.systemUsersColumnToggleMenu.getMenuItem('User details');
|
||||||
|
expect(displayNameMenuItem).toBeDisabled();
|
||||||
|
|
||||||
|
// * Verify that 'Actions' is disabled
|
||||||
|
const actionsMenuItem = await systemConsolePage.systemUsersColumnToggleMenu.getMenuItem('Actions');
|
||||||
|
expect(actionsMenuItem).toBeDisabled();
|
||||||
|
|
||||||
|
// * Verify that 'Email' however is enabled
|
||||||
|
const emailMenuItem = await systemConsolePage.systemUsersColumnToggleMenu.getMenuItem('Email');
|
||||||
|
expect(emailMenuItem).not.toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5523-5 Should show/hide the columns which are toggled on/off', async ({pw, pages}) => {
|
||||||
|
const {adminUser} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// # Open the column toggle menu
|
||||||
|
await systemConsolePage.systemUsers.openColumnToggleMenu();
|
||||||
|
await systemConsolePage.systemUsersColumnToggleMenu.toBeVisible();
|
||||||
|
|
||||||
|
// # Uncheck the Email and Last login columns to hide them
|
||||||
|
await systemConsolePage.systemUsersColumnToggleMenu.clickMenuItem('Email');
|
||||||
|
await systemConsolePage.systemUsersColumnToggleMenu.clickMenuItem('Last login');
|
||||||
|
|
||||||
|
// * Close the column toggle menu
|
||||||
|
await systemConsolePage.systemUsersColumnToggleMenu.close();
|
||||||
|
|
||||||
|
// * Verify that Email column and Last login column are hidden
|
||||||
|
expect(await systemConsolePage.systemUsers.doesColumnExist('Email')).toBe(false);
|
||||||
|
expect(await systemConsolePage.systemUsers.doesColumnExist('Last login')).toBe(false);
|
||||||
|
|
||||||
|
// # Now open the column toggle menu again
|
||||||
|
await systemConsolePage.systemUsers.openColumnToggleMenu();
|
||||||
|
|
||||||
|
// # Check the Email column to show it
|
||||||
|
await systemConsolePage.systemUsersColumnToggleMenu.clickMenuItem('Email');
|
||||||
|
|
||||||
|
// * Close the column toggle menu
|
||||||
|
await systemConsolePage.systemUsersColumnToggleMenu.close();
|
||||||
|
|
||||||
|
// * Verify that Email column is now shown
|
||||||
|
expect(await systemConsolePage.systemUsers.doesColumnExist('Email')).toBe(true);
|
||||||
|
|
||||||
|
// * Verify that however Last login column is still hidden as we did not check it on
|
||||||
|
expect(await systemConsolePage.systemUsers.doesColumnExist('Last login')).toBe(false);
|
||||||
|
});
|
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {expect} from '@playwright/test';
|
||||||
|
|
||||||
|
import {test} from '@e2e-support/test_fixture';
|
||||||
|
import {duration} from '@e2e-support/util';
|
||||||
|
import {components} from '@e2e-support/ui/components';
|
||||||
|
|
||||||
|
test('MM-T5522 Should begin export of data when export button is pressed', async ({pw, pages}) => {
|
||||||
|
test.slow();
|
||||||
|
|
||||||
|
// # Skip test if no license
|
||||||
|
await pw.skipIfNoLicense();
|
||||||
|
|
||||||
|
const {adminUser} = await pw.initSetup();
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// # Change the export duration to 30 days
|
||||||
|
await systemConsolePage.systemUsers.dateRangeSelectorMenuButton.click();
|
||||||
|
await systemConsolePage.systemUsersDateRangeMenu.clickMenuItem('All time');
|
||||||
|
|
||||||
|
// # Click Export button and confirm the modal
|
||||||
|
await systemConsolePage.systemUsers.exportButton.click();
|
||||||
|
const confirmModal = new components.GenericConfirmModal(page, 'exportUserDataModal');
|
||||||
|
await confirmModal.confirm();
|
||||||
|
|
||||||
|
// # Change the export duration to all time
|
||||||
|
await systemConsolePage.systemUsers.dateRangeSelectorMenuButton.click();
|
||||||
|
await systemConsolePage.systemUsersDateRangeMenu.clickMenuItem('Last 30 days');
|
||||||
|
|
||||||
|
// # Click Export button and confirm the modal
|
||||||
|
await systemConsolePage.systemUsers.exportButton.click();
|
||||||
|
await confirmModal.confirm();
|
||||||
|
|
||||||
|
// # Click Export again button and confirm the modal
|
||||||
|
await systemConsolePage.systemUsers.exportButton.click();
|
||||||
|
await confirmModal.confirm();
|
||||||
|
|
||||||
|
// * Verify that we are told that one is already running
|
||||||
|
expect(page.getByText('Export is in progress')).toBeVisible();
|
||||||
|
|
||||||
|
// # Go back to Channels and open the system bot DM
|
||||||
|
const channelsPage = new pages.ChannelsPage(page);
|
||||||
|
channelsPage.goto('ad-1/messages', '@system-bot');
|
||||||
|
await channelsPage.centerView.toBeVisible();
|
||||||
|
|
||||||
|
// * Verify that we have started the export and that the second one is running second
|
||||||
|
const lastPost = await channelsPage.centerView.getLastPost();
|
||||||
|
const postText = await lastPost.body.innerText();
|
||||||
|
expect(postText).toContain('export of user data for the last 30 days');
|
||||||
|
|
||||||
|
// * Wait until the first export finishes
|
||||||
|
await channelsPage.centerView.waitUntilLastPostContains('contains user data for all time', duration.half_min);
|
||||||
|
|
||||||
|
// * Wait until the second export finishes
|
||||||
|
await channelsPage.centerView.waitUntilLastPostContains(
|
||||||
|
'contains user data for the last 30 days',
|
||||||
|
duration.half_min,
|
||||||
|
);
|
||||||
|
});
|
@ -0,0 +1,166 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {test} from '@e2e-support/test_fixture';
|
||||||
|
import {createRandomTeam, createRandomUser} from '@e2e-support/server';
|
||||||
|
|
||||||
|
test('MM-T5521-7 Should be able to filter users with team filter', async ({pw, pages}) => {
|
||||||
|
const {adminUser, adminClient} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Create a team with a user
|
||||||
|
const team1 = await adminClient.createTeam(createRandomTeam());
|
||||||
|
const user1 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
await adminClient.addToTeam(team1.id, user1.id);
|
||||||
|
|
||||||
|
// # Create another team with a user
|
||||||
|
const team2 = await adminClient.createTeam(createRandomTeam());
|
||||||
|
const user2 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
await adminClient.addToTeam(team2.id, user2.id);
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// # Open the filter's popover
|
||||||
|
await systemConsolePage.systemUsers.openFilterPopover();
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.toBeVisible();
|
||||||
|
|
||||||
|
// # Enter the team name of the first user and select it
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.searchInTeamMenu(team1.display_name);
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.teamMenuInput.press('Enter');
|
||||||
|
|
||||||
|
// # Save the filter and close the popover
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.save();
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.close();
|
||||||
|
await systemConsolePage.systemUsers.isLoadingComplete();
|
||||||
|
|
||||||
|
// * Verify that the user corresponding to the first team is visible as team-1 filter was applied
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsFound(user1.email);
|
||||||
|
|
||||||
|
// * Verify that the user corresponding to the second team is not visible as team-2 filter was not applied
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsNotFound(user2.email);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5521-8 Should be able to filter users with role filter', async ({pw, pages}) => {
|
||||||
|
const {adminUser, adminClient} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Create a guest user
|
||||||
|
const guestUser = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
await adminClient.updateUserRoles(guestUser.id, 'system_guest');
|
||||||
|
|
||||||
|
// # Create a regular user
|
||||||
|
const regularUser = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// # Open the filter popover
|
||||||
|
await systemConsolePage.systemUsers.openFilterPopover();
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.toBeVisible();
|
||||||
|
|
||||||
|
// # Open the role filter in the popover
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.openRoleMenu();
|
||||||
|
await systemConsolePage.systemUsersRoleMenu.toBeVisible();
|
||||||
|
|
||||||
|
// # Select the Guest role from the role filter
|
||||||
|
await systemConsolePage.systemUsersRoleMenu.clickMenuItem('Guest');
|
||||||
|
await systemConsolePage.systemUsersRoleMenu.close();
|
||||||
|
|
||||||
|
// # Save the filter and close the popover
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.save();
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.close();
|
||||||
|
await systemConsolePage.systemUsers.isLoadingComplete();
|
||||||
|
|
||||||
|
// # Search for the guest user with the filter already applied
|
||||||
|
await systemConsolePage.systemUsers.enterSearchText(guestUser.email);
|
||||||
|
|
||||||
|
// * Verify that guest user is visible as a 'Guest' role filter was applied
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsFound(guestUser.email);
|
||||||
|
|
||||||
|
// # Search for the regular user with the filter already applied
|
||||||
|
await systemConsolePage.systemUsers.enterSearchText(regularUser.email);
|
||||||
|
|
||||||
|
// * Verify that regular user is not visible as 'Guest' role filter was applied
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsFound('No data');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5521-9 Should be able to filter users with status filter', async ({pw, pages}) => {
|
||||||
|
const {adminUser, adminClient} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Create a user and then deactivate it
|
||||||
|
const deactivatedUser = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
await adminClient.updateUserActive(deactivatedUser.id, false);
|
||||||
|
|
||||||
|
// # Create a regular user
|
||||||
|
const regularUser = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// # Open the filter popover
|
||||||
|
await systemConsolePage.systemUsers.openFilterPopover();
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.toBeVisible();
|
||||||
|
|
||||||
|
// # Open the status filter in the popover
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.openStatusMenu();
|
||||||
|
await systemConsolePage.systemUsersStatusMenu.toBeVisible();
|
||||||
|
await systemConsolePage.systemUsers.isLoadingComplete();
|
||||||
|
|
||||||
|
// # Select the Deactivated users from the status filter
|
||||||
|
await systemConsolePage.systemUsersStatusMenu.clickMenuItem('Deactivated users');
|
||||||
|
await systemConsolePage.systemUsersStatusMenu.close();
|
||||||
|
|
||||||
|
// # Save the filter and close the popover
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.save();
|
||||||
|
await systemConsolePage.systemUsersFilterPopover.close();
|
||||||
|
|
||||||
|
// # Search for the deactivated user with the filter already applied
|
||||||
|
await systemConsolePage.systemUsers.enterSearchText(deactivatedUser.email);
|
||||||
|
|
||||||
|
// * Verify that deactivated user is visible as a 'Deactivated' status filter was applied
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsFound(deactivatedUser.email);
|
||||||
|
|
||||||
|
// # Search for the regular user with the filter already applied
|
||||||
|
await systemConsolePage.systemUsers.enterSearchText(regularUser.email);
|
||||||
|
|
||||||
|
// * Verify that regular user is not visible as 'Deactivated' status filter was applied
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsFound('No data');
|
||||||
|
});
|
@ -0,0 +1,194 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {test} from '@e2e-support/test_fixture';
|
||||||
|
import {createRandomUser} from '@e2e-support/server';
|
||||||
|
import {getRandomId} from '@e2e-support/util';
|
||||||
|
|
||||||
|
test('MM-T5521-1 Should be able to search users with their first names', async ({pw, pages}) => {
|
||||||
|
const {adminUser, adminClient} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Create 2 users
|
||||||
|
const user1 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
const user2 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// # Enter the 'First Name' of the first user in the search box
|
||||||
|
await systemConsolePage.systemUsers.enterSearchText(user1.first_name);
|
||||||
|
|
||||||
|
// * Verify that the searched user i.e first user is found in the list
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsFound(user1.email);
|
||||||
|
|
||||||
|
// * Verify that the second user doesnt appear in the list
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsNotFound(user2.email);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5521-2 Should be able to search users with their last names', async ({pw, pages}) => {
|
||||||
|
const {adminUser, adminClient} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Create 2 users
|
||||||
|
const user1 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
const user2 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// # Enter the 'Last Name' of the user in the search box
|
||||||
|
await systemConsolePage.systemUsers.enterSearchText(user1.last_name);
|
||||||
|
|
||||||
|
// * Verify that the searched user i.e first user is found in the list
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsFound(user1.email);
|
||||||
|
|
||||||
|
// * Verify that the second user doesnt appear in the list
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsNotFound(user2.email);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5521-3 Should be able to search users with their emails', async ({pw, pages}) => {
|
||||||
|
const {adminUser, adminClient} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Create 2 users
|
||||||
|
const user1 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
const user2 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// * Enter the 'Email' of the first user in the search box
|
||||||
|
await systemConsolePage.systemUsers.enterSearchText(user1.email);
|
||||||
|
|
||||||
|
// * Verify that the searched user i.e first user is found in the list
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsFound(user1.email);
|
||||||
|
|
||||||
|
// * Verify that the second user doesnt appear in the list
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsNotFound(user2.email);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5521-4 Should be able to search users with their usernames', async ({pw, pages}) => {
|
||||||
|
const {adminUser, adminClient} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Create 2 users
|
||||||
|
const user1 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
const user2 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
await systemConsolePage.systemUsers.toBeVisible();
|
||||||
|
|
||||||
|
// # Enter the 'Username' of the first user in the search box
|
||||||
|
await systemConsolePage.systemUsers.enterSearchText(user1.username);
|
||||||
|
|
||||||
|
// * Verify that the searched user i.e first user is found in the list
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsFound(user1.email);
|
||||||
|
|
||||||
|
// * Verify that the another user is not visible
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsNotFound(user2.email);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5521-5 Should be able to search users with their nick names', async ({pw, pages}) => {
|
||||||
|
const {adminUser, adminClient} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Create 2 users
|
||||||
|
const user1 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
const user2 = await adminClient.createUser(createRandomUser(), '', '');
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
|
||||||
|
// # Enter the 'Nickname' of the first user in the search box
|
||||||
|
await systemConsolePage.systemUsers.enterSearchText(user1.nickname);
|
||||||
|
|
||||||
|
// * Verify that the searched user i.e first user is found in the list
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsFound(user1.email);
|
||||||
|
|
||||||
|
// * Verify that the second user doesnt appear in the list
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsNotFound(user2.email);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MM-T5521-6 Should show no user is found when user doesnt exists', async ({pw, pages}) => {
|
||||||
|
const {adminUser} = await pw.initSetup();
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
throw new Error('Failed to create admin user');
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Log in as admin
|
||||||
|
const {page} = await pw.testBrowser.login(adminUser);
|
||||||
|
|
||||||
|
// # Visit system console
|
||||||
|
const systemConsolePage = new pages.SystemConsolePage(page);
|
||||||
|
await systemConsolePage.goto();
|
||||||
|
await systemConsolePage.toBeVisible();
|
||||||
|
|
||||||
|
// # Go to Users section
|
||||||
|
await systemConsolePage.sidebar.goToItem('Users');
|
||||||
|
|
||||||
|
// # Enter random text in the search box
|
||||||
|
await systemConsolePage.systemUsers.enterSearchText(`!${getRandomId(15)}_^^^_${getRandomId(15)}!`);
|
||||||
|
|
||||||
|
await systemConsolePage.systemUsers.verifyRowWithTextIsFound('No data');
|
||||||
|
});
|
@ -71,6 +71,7 @@ export function ExportUserDataModal({onConfirm, onExited}: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfirmModalRedux
|
<ConfirmModalRedux
|
||||||
|
id='exportUserDataModal'
|
||||||
title={title}
|
title={title}
|
||||||
message={message}
|
message={message}
|
||||||
confirmButtonText={exportDataButton}
|
confirmButtonText={exportDataButton}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Modal} from 'react-bootstrap';
|
import {Modal} from 'react-bootstrap';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
@ -8,6 +9,7 @@ import {FormattedMessage} from 'react-intl';
|
|||||||
import './confirm_modal.scss';
|
import './confirm_modal.scss';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
id?: string;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set to show modal
|
* Set to show modal
|
||||||
@ -165,12 +167,12 @@ export default class ConfirmModal extends React.Component<Props, State> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
|
id={classNames('confirmModal', this.props.id)}
|
||||||
className={'modal-confirm ' + this.props.modalClass}
|
className={'modal-confirm ' + this.props.modalClass}
|
||||||
dialogClassName='a11y__modal'
|
dialogClassName='a11y__modal'
|
||||||
show={this.props.show}
|
show={this.props.show}
|
||||||
onHide={this.handleCancel}
|
onHide={this.handleCancel}
|
||||||
onExited={this.props.onExited}
|
onExited={this.props.onExited}
|
||||||
id='confirmModal'
|
|
||||||
role='dialog'
|
role='dialog'
|
||||||
aria-modal={true}
|
aria-modal={true}
|
||||||
aria-labelledby='confirmModalLabel'
|
aria-labelledby='confirmModalLabel'
|
||||||
|
Loading…
Reference in New Issue
Block a user