Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
@@ -2,13 +2,13 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Client4} from '@mattermost/client';
|
||||
import {UserProfile} from '@mattermost/types/users';
|
||||
import {PluginManifest} from '@mattermost/types/plugins';
|
||||
import {PreferenceType} from '@mattermost/types/preferences';
|
||||
import {UserProfile} from '@mattermost/types/users';
|
||||
|
||||
import {defaultTeam} from './util';
|
||||
import {createRandomTeam, getAdminClient, getDefaultAdminUser, makeClient} from './server';
|
||||
import {testConfig} from './test_config';
|
||||
import {defaultTeam} from './util';
|
||||
|
||||
export async function baseGlobalSetup() {
|
||||
let adminClient: Client4;
|
||||
|
||||
@@ -2,10 +2,25 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Client4} from '@mattermost/client';
|
||||
import {AdminConfig} from '@mattermost/types/config';
|
||||
import {UserProfile} from '@mattermost/types/users';
|
||||
|
||||
import {testConfig} from '@/test_config';
|
||||
|
||||
// Extend Client4 with methods used for testing
|
||||
declare module '@mattermost/client' {
|
||||
interface Client4 {
|
||||
updateConfigX: (config: Partial<AdminConfig>) => Promise<AdminConfig>;
|
||||
}
|
||||
}
|
||||
|
||||
// updateConfigX merges the given config with the current config and updates it to the server
|
||||
Client4.prototype.updateConfigX = async function (this: Client4, config: Partial<AdminConfig>) {
|
||||
const currentConfig = await this.getConfig();
|
||||
const newConfig = {...currentConfig, ...config};
|
||||
return await this.updateConfig(newConfig);
|
||||
};
|
||||
|
||||
// Variable to hold cache
|
||||
const clients: Record<string, ClientCache> = {};
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ import DeletePostConfirmationDialog from './channels/delete_post_confirmation_di
|
||||
import RestorePostConfirmationDialog from './channels/restore_post_confirmation_dialog';
|
||||
import SystemConsoleFeatureDiscovery from './system_console/sections/system_users/feature_discovery';
|
||||
import SystemConsoleMobileSecurity from './system_console/sections/system_users/mobile_security';
|
||||
import SystemConsoleNotifications from './system_console/sections/site_configuration/notifications';
|
||||
import ScheduledPost from './channels/scheduled_post';
|
||||
import SendMessageNowModal from './channels/send_message_now_modal';
|
||||
import DeleteScheduledPostModal from './channels/delete_scheduled_post_modal';
|
||||
@@ -83,6 +84,7 @@ const components = {
|
||||
SystemUsersColumnToggleMenu,
|
||||
SystemConsoleFeatureDiscovery,
|
||||
SystemConsoleMobileSecurity,
|
||||
SystemConsoleNotifications,
|
||||
MessagePriority,
|
||||
UserProfilePopover,
|
||||
UserAccountMenu,
|
||||
@@ -130,6 +132,7 @@ export {
|
||||
SystemUsersColumnToggleMenu,
|
||||
SystemConsoleFeatureDiscovery,
|
||||
SystemConsoleMobileSecurity,
|
||||
SystemConsoleNotifications,
|
||||
MessagePriority,
|
||||
UserProfilePopover,
|
||||
UserAccountMenu,
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Locator, expect} from '@playwright/test';
|
||||
|
||||
/**
|
||||
* System Console -> Site Configuration -> Notifications
|
||||
*/
|
||||
export default class SystemConsoleNotifications {
|
||||
readonly container: Locator;
|
||||
|
||||
// header
|
||||
readonly header: Locator;
|
||||
|
||||
// Notification Display Name
|
||||
readonly notificationDisplayName: Locator;
|
||||
readonly notificationDisplayNameInput: Locator;
|
||||
readonly notificationDisplayNameHelpText: Locator;
|
||||
|
||||
// Notification From Address
|
||||
readonly notificationFromAddress: Locator;
|
||||
readonly notificationFromAddressInput: Locator;
|
||||
readonly notificationFromAddressHelpText: Locator;
|
||||
|
||||
// Support Email Address
|
||||
readonly supportEmailAddress: Locator;
|
||||
readonly supportEmailAddressInput: Locator;
|
||||
readonly supportEmailHelpText: Locator;
|
||||
|
||||
// Push Notification Contents
|
||||
readonly pushNotificationContents: Locator;
|
||||
readonly pushNotificationContentsDropdown: Locator;
|
||||
readonly pushNotificationContentsHelpText: Locator;
|
||||
|
||||
// Save button
|
||||
readonly saveButton: Locator;
|
||||
readonly errorMessage: Locator;
|
||||
|
||||
constructor(container: Locator) {
|
||||
this.container = container;
|
||||
|
||||
// header
|
||||
this.header = this.container.locator('.admin-console__header').getByText('Notifications');
|
||||
|
||||
// Notification Display Name
|
||||
this.notificationDisplayName = this.container.getByTestId('EmailSettings.FeedbackNameinput');
|
||||
this.notificationDisplayNameInput = this.container.getByTestId('EmailSettings.FeedbackNameinput');
|
||||
this.notificationDisplayNameHelpText = this.container.getByTestId('EmailSettings.FeedbackNamehelp-text');
|
||||
|
||||
// Notification From Address
|
||||
this.notificationFromAddress = this.container.getByLabel('Notification From Address:');
|
||||
this.notificationFromAddressInput = this.container.getByTestId('EmailSettings.FeedbackEmailinput');
|
||||
this.notificationFromAddressHelpText = this.container.getByTestId('EmailSettings.FeedbackEmailhelp-text');
|
||||
|
||||
// Support Email Address
|
||||
this.supportEmailAddress = this.container.getByLabel('Support Email Address:');
|
||||
this.supportEmailAddressInput = this.container.getByTestId('SupportSettings.SupportEmailinput');
|
||||
this.supportEmailHelpText = this.container.getByTestId('SupportSettings.SupportEmailhelp-text');
|
||||
|
||||
// Push Notification Contents
|
||||
this.pushNotificationContents = this.container.getByTestId('EmailSettings.PushNotificationContents');
|
||||
this.pushNotificationContentsDropdown = this.container.getByTestId(
|
||||
'EmailSettings.PushNotificationContentsdropdown',
|
||||
);
|
||||
this.pushNotificationContentsHelpText = this.container.getByTestId(
|
||||
'EmailSettings.PushNotificationContentshelp-text',
|
||||
);
|
||||
|
||||
// Save button and error message
|
||||
this.saveButton = this.container.getByTestId('saveSetting');
|
||||
this.errorMessage = this.container.locator('.has-error');
|
||||
}
|
||||
|
||||
async toBeVisible() {
|
||||
await expect(this.container).toBeVisible();
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,11 @@ export default class SystemConsolePage {
|
||||
readonly sidebar;
|
||||
readonly navbar;
|
||||
|
||||
// Site Configuration
|
||||
|
||||
// System Console > Notifications
|
||||
readonly notifications;
|
||||
|
||||
/**
|
||||
* System Console -> User Management -> Users
|
||||
*/
|
||||
@@ -34,6 +39,12 @@ export default class SystemConsolePage {
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
|
||||
// Site Configuration
|
||||
// System Console > Notifications
|
||||
this.notifications = new components.SystemConsoleNotifications(
|
||||
page.getByTestId('sysconsole_section_notifications'),
|
||||
);
|
||||
|
||||
// Areas of the page
|
||||
this.navbar = new components.SystemConsoleNavbar(page.locator('.backstage-navbar'));
|
||||
this.sidebar = new components.SystemConsoleSidebar(page.locator('.admin-sidebar'));
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {AdminConfig} from '@mattermost/types/config';
|
||||
|
||||
import {expect, test} from '@mattermost/playwright-lib';
|
||||
|
||||
/**
|
||||
* @objective Verify that the Push Notification Contents setting is properly displayed and can be changed to all available options
|
||||
*/
|
||||
test('Push Notification Contents setting displays correctly and saves all options', async ({pw}) => {
|
||||
const {adminUser, adminClient} = await pw.initSetup();
|
||||
|
||||
// # Update to default config
|
||||
await adminClient.updateConfigX({
|
||||
EmailSettings: {
|
||||
PushNotificationContents: 'full',
|
||||
FeedbackName: 'Mattermost Test Team',
|
||||
FeedbackEmail: 'feedback@mattertest.com',
|
||||
},
|
||||
SupportSettings: {
|
||||
SupportEmail: 'support@mattertest.com',
|
||||
},
|
||||
} as Partial<AdminConfig>);
|
||||
|
||||
if (!adminUser) {
|
||||
throw new Error('Failed to get admin user');
|
||||
}
|
||||
|
||||
// # Log in as admin
|
||||
const {systemConsolePage} = await pw.testBrowser.login(adminUser);
|
||||
|
||||
// # Visit Notifications admin console page
|
||||
await systemConsolePage.goto();
|
||||
await systemConsolePage.toBeVisible();
|
||||
await systemConsolePage.sidebar.goToItem('Notifications');
|
||||
|
||||
// # Wait for Notifications section to load
|
||||
const notifications = systemConsolePage.notifications;
|
||||
await notifications.toBeVisible();
|
||||
|
||||
// * Verify that setting is visible and matches text content
|
||||
await notifications.pushNotificationContents.scrollIntoViewIfNeeded();
|
||||
await expect(notifications.pushNotificationContents).toBeVisible();
|
||||
|
||||
// * Verify that the help text is visible and matches text content
|
||||
const helpText = notifications.pushNotificationContentsHelpText;
|
||||
await expect(helpText).toBeVisible();
|
||||
|
||||
const contents = [
|
||||
'Generic description with only sender name',
|
||||
' - Includes only the name of the person who sent the message in push notifications, with no information about channel name or message contents. ',
|
||||
'Generic description with sender and channel names',
|
||||
' - Includes the name of the person who sent the message and the channel it was sent in, but not the message contents. ',
|
||||
'Full message content sent in the notification payload',
|
||||
" - Includes the message contents in the push notification payload that is relayed through Apple's Push Notification Service (APNS) or Google's Firebase Cloud Messaging (FCM). It is ",
|
||||
'highly recommended',
|
||||
' this option only be used with an "https" protocol to encrypt the connection and protect confidential information sent in messages.',
|
||||
'Full message content fetched from the server on receipt',
|
||||
' - The notification payload relayed through APNS or FCM contains no message content, instead it contains a unique message ID used to fetch message content from the server when a push notification is received by a device. If the server cannot be reached, a generic notification will be displayed.',
|
||||
];
|
||||
await expect(helpText).toHaveText(contents.join(''));
|
||||
|
||||
const strongElements = helpText.locator('strong');
|
||||
await expect(strongElements.nth(0)).toHaveText(contents[0]);
|
||||
await expect(strongElements.nth(1)).toHaveText(contents[2]);
|
||||
await expect(strongElements.nth(2)).toHaveText(contents[4]);
|
||||
await expect(strongElements.nth(3)).toHaveText(contents[6]);
|
||||
await expect(strongElements.nth(4)).toHaveText(contents[8]);
|
||||
|
||||
// * Verify that the option/dropdown is visible and has default value
|
||||
const dropdown = notifications.pushNotificationContentsDropdown;
|
||||
await expect(dropdown).toBeVisible();
|
||||
await expect(dropdown).toHaveValue('full');
|
||||
|
||||
const options = [
|
||||
{label: 'Generic description with only sender name', value: 'generic_no_channel'},
|
||||
{label: 'Generic description with sender and channel names', value: 'generic'},
|
||||
{label: 'Full message content sent in the notification payload', value: 'full'},
|
||||
{label: 'Full message content fetched from the server on receipt', value: 'id_loaded'},
|
||||
];
|
||||
|
||||
// # Select each value and save
|
||||
// * Verify that the config is correctly saved in the server
|
||||
for (const option of options) {
|
||||
await dropdown.selectOption({label: option.label});
|
||||
await expect(dropdown).toHaveValue(option.value);
|
||||
|
||||
await notifications.saveButton.click();
|
||||
|
||||
// * Verify config is saved
|
||||
const {adminClient} = await pw.getAdminClient();
|
||||
const config = await adminClient.getConfig();
|
||||
expect(config.EmailSettings?.PushNotificationContents).toBe(option.value);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @objective Verify that the Support Email setting can be changed and saved
|
||||
*/
|
||||
test('MM-T1210 Can change Support Email setting', async ({pw}) => {
|
||||
const {adminUser} = await pw.getAdminClient();
|
||||
|
||||
if (!adminUser) {
|
||||
throw new Error('Failed to get admin user');
|
||||
}
|
||||
|
||||
// # Log in as admin
|
||||
const {systemConsolePage} = await pw.testBrowser.login(adminUser);
|
||||
|
||||
// # Visit Notifications admin console page
|
||||
await systemConsolePage.goto();
|
||||
await systemConsolePage.toBeVisible();
|
||||
await systemConsolePage.sidebar.goToItem('Notifications');
|
||||
|
||||
// # Wait for Notifications section to load
|
||||
const notifications = systemConsolePage.notifications;
|
||||
await notifications.toBeVisible();
|
||||
|
||||
// # Scroll Support Email section into view and verify that it's visible
|
||||
const supportEmailSetting = notifications.supportEmailAddress;
|
||||
await supportEmailSetting.scrollIntoViewIfNeeded();
|
||||
await expect(supportEmailSetting).toBeVisible();
|
||||
|
||||
// * Verify that the help text is visible and matches text content
|
||||
await expect(notifications.supportEmailHelpText).toBeVisible();
|
||||
await expect(notifications.supportEmailHelpText).toHaveText('Email address displayed on support emails.');
|
||||
|
||||
// # Clear and type new email
|
||||
const newEmail = 'changed_for_test_support@example.com';
|
||||
await notifications.supportEmailAddressInput.clear();
|
||||
await notifications.supportEmailAddressInput.fill(newEmail);
|
||||
|
||||
// * Verify that set value is visible and matches text
|
||||
await expect(notifications.supportEmailAddressInput).toHaveValue(newEmail);
|
||||
|
||||
// # Save setting
|
||||
await notifications.saveButton.click();
|
||||
|
||||
// * Verify that the config is correctly saved in the server
|
||||
const {adminClient} = await pw.getAdminClient();
|
||||
const config = await adminClient.getConfig();
|
||||
expect(config.SupportSettings?.SupportEmail).toBe(newEmail);
|
||||
});
|
||||
|
||||
/**
|
||||
* @objective Verify that the save button is disabled when mandatory fields are empty
|
||||
*/
|
||||
test('MM-41671 cannot save the notifications page if mandatory fields are missing', async ({pw}) => {
|
||||
const {adminUser} = await pw.getAdminClient();
|
||||
if (!adminUser) {
|
||||
throw new Error('Failed to get admin user');
|
||||
}
|
||||
|
||||
// # Log in as admin
|
||||
const {systemConsolePage} = await pw.testBrowser.login(adminUser);
|
||||
|
||||
// # Visit Notifications admin console page
|
||||
await systemConsolePage.goto();
|
||||
await systemConsolePage.toBeVisible();
|
||||
await systemConsolePage.sidebar.goToItem('Notifications');
|
||||
|
||||
// # Wait for Notifications section to load
|
||||
const notifications = systemConsolePage.notifications;
|
||||
await notifications.toBeVisible();
|
||||
|
||||
const tests = [
|
||||
{name: 'Support Email Address', fieldInput: notifications.supportEmailAddressInput},
|
||||
{name: 'Notification Display Name', fieldInput: notifications.notificationDisplayNameInput},
|
||||
{name: 'Notification From Address', fieldInput: notifications.notificationFromAddressInput},
|
||||
];
|
||||
|
||||
for (const testCase of tests) {
|
||||
// # Clear the field
|
||||
await expect(testCase.fieldInput).toBeVisible();
|
||||
await testCase.fieldInput.clear();
|
||||
|
||||
// * Error message is shown and save button is disabled
|
||||
await expect(notifications.errorMessage).toHaveText(`"${testCase.name}" is required`);
|
||||
await expect(notifications.saveButton).toBeDisabled();
|
||||
|
||||
// # Insert something in the field
|
||||
await testCase.fieldInput.fill('anything');
|
||||
|
||||
// * Ensure no error message is shown and the save button is not disabled
|
||||
await expect(notifications.errorMessage).toHaveCount(0);
|
||||
await expect(notifications.saveButton).not.toBeDisabled();
|
||||
}
|
||||
});
|
||||
Ссылка в новой задаче
Block a user