Этот коммит содержится в:
Mario Vitale
2023-03-27 16:28:42 +02:00
родитель da7a6825ce
Коммит ba6b97fb62
1142 изменённых файлов: 44 добавлений и 44 удалений

Просмотреть файл

@@ -0,0 +1,24 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @not_cloud @system_console @restrict_system_admin
describe('Password settings', () => {
it('MM-T4679 - Should NOT show MaximumLoginAttempts when ExperimentalSettings.RestrictSystemAdmin is true', () => {
cy.apiUpdateConfig({
ExperimentalSettings: {
RestrictSystemAdmin: true,
},
}).then(() => {
cy.visit('/admin_console/authentication/password');
cy.get('#maximumLoginAttempts').should('not.exist');
});
});
});

Просмотреть файл

@@ -0,0 +1,146 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Group: @channels @system_console
describe('Custom Terms of Service', () => {
let testUser;
let testTeam;
before(() => {
cy.apiInitSetup().then(({team, user}) => {
testUser = user;
testTeam = team;
});
});
it('MM-T1190 - Appears after creating new account and verifying email address', () => {
const customTermsOfServiceText = 'Test custom terms of service';
// # Verify new user email
cy.apiVerifyUserEmailById(testUser.id);
// # Login as admin
cy.apiAdminLogin();
cy.apiUpdateConfig({
EmailSettings: {
RequireEmailVerification: true,
},
});
// # Visit custom terms of service page
cy.visit('/admin_console/compliance/custom_terms_of_service');
// # Enable custom terms of service
cy.findByTestId('SupportSettings.CustomTermsOfServiceEnabledtrue').click();
// # Set the terms of service to the first value
cy.findByTestId('SupportSettings.CustomTermsOfServiceTextinput').clear().type(customTermsOfServiceText);
// # Save config
cy.get('#saveSetting').click();
// # Login as the test user
cy.apiLogin(testUser);
// # Visit the test team town square
cy.visit(`/${testTeam.name}/channels/town-square`);
// * Ensure that the terms of service text shows as expected
cy.findByTestId('termsOfService').should('be.visible').and('contain.text', customTermsOfServiceText);
// * Ensure that the accept terms button is visible and click it
cy.get('#acceptTerms').should('be.visible').click();
// * Ensure the user is redirected to the appropriate team after terms are accepted
cy.url().should('include', `/${testTeam.name}/channels/town-square`);
});
it('MM-T1191 - Repeated edits must be agreed to', () => {
const firstTOS = 'First custom terms of service';
const secondTOS = 'Second custom terms of service';
// # Login as admin
cy.apiAdminLogin();
// # Reset config via the API from previous test
cy.apiUpdateConfig({
EmailSettings: {
RequireEmailVerification: false,
},
SupportSettings: {
CustomTermsOfServiceEnabled: false,
},
});
// # Visit custom terms of service page
cy.visit('/admin_console/compliance/custom_terms_of_service');
// # Enable custom terms of service
cy.findByTestId('SupportSettings.CustomTermsOfServiceEnabledtrue').click();
// # Set the terms of service to the first value
cy.findByTestId('SupportSettings.CustomTermsOfServiceTextinput').clear().type(firstTOS);
// # Save config
cy.get('#saveSetting').click();
// # Accept the terms as sysadmin
cy.get('#acceptTerms').should('be.visible').click();
// * Should be redirected back to custom terms of service page
cy.url().should('include', '/admin_console/compliance/custom_terms_of_service');
// # Login as the test user
cy.apiLogin(testUser);
// # Visit the test team town square
cy.visit(`/${testTeam.name}/channels/town-square`);
// * Ensure that the first terms of service is visible
cy.findByTestId('termsOfService').should('be.visible').and('contain.text', firstTOS);
// # Login as admin
cy.apiAdminLogin();
// # Visit custom terms of service page
cy.visit('/admin_console/compliance/custom_terms_of_service');
// # Set the terms of service to the first value
cy.findByTestId('SupportSettings.CustomTermsOfServiceTextinput').clear().type(secondTOS);
// # Save config
cy.get('#saveSetting').click();
// * Ensure that the terms of service text shows as expected
cy.findByTestId('termsOfService').should('be.visible').and('contain.text', secondTOS);
// # Accept the terms as sysadmin
cy.get('#acceptTerms').should('be.visible').click();
// * Should be redirected back to custom terms of service page
cy.url().should('include', '/admin_console/compliance/custom_terms_of_service');
// # Login as the test user
cy.apiLogin(testUser);
// # Visit the test team town square
cy.visit(`/${testTeam.name}/channels/town-square`);
// * Ensure that the new terms of service is visible
cy.findByTestId('termsOfService').should('be.visible').and('contain.text', secondTOS);
// * Ensure that the accept terms button is visible and click it
cy.get('#acceptTerms').should('be.visible').click();
// * Ensure the user is redirected to the appropriate team after terms are accepted
cy.url().should('include', `/${testTeam.name}/channels/town-square`);
});
});

Просмотреть файл

@@ -0,0 +1,46 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console @smoke
import * as TIMEOUTS from '../../../fixtures/timeouts';
import {getAdminAccount} from '../../../support/env';
describe('System Console', () => {
const sysadmin = getAdminAccount();
let testUser;
before(() => {
// # Create new team and login
cy.apiInitSetup({loginAfter: true}).then(({user}) => {
testUser = user;
});
});
it('MM-T922 Demoted user cannot continue to view System Console', () => {
const baseUrl = Cypress.config('baseUrl');
// # Set user to be a sysadmin, so it can access the system console
cy.externalRequest({user: sysadmin, method: 'put', baseUrl, path: `users/${testUser.id}/roles`, data: {roles: 'system_user system_admin'}});
// # Visit a page on the system console
cy.visit('/admin_console/reporting/system_analytics');
cy.get('#adminConsoleWrapper').should('be.visible');
cy.url().should('include', '/admin_console/reporting/system_analytics');
// # Change the role of the user back to user
cy.externalRequest({user: sysadmin, method: 'put', baseUrl, path: `users/${testUser.id}/roles`, data: {roles: 'system_user'}});
// # User should get redirected to town square
cy.get('#adminConsoleWrapper').should('not.exist');
cy.get('#postListContent', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible');
cy.url().should('include', 'town-square');
});
});

Просмотреть файл

@@ -0,0 +1,303 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @not_cloud
import * as TIMEOUTS from '../../../fixtures/timeouts';
describe('Environment', () => {
let townsquareLink;
let testTeam;
const mattermostIcon = 'mattermost-icon_128x128.png';
before(() => {
cy.shouldNotRunOnCloudEdition();
cy.apiInitSetup().then(({team}) => {
testTeam = team;
townsquareLink = `/${team.name}/channels/town-square`;
});
});
it('MM-T959 - Web server mode - Webserver gzip', () => {
cy.visit('/admin_console/environment/web_server');
// # Click dropdown to open selection
cy.findByTestId('ServiceSettings.WebserverModedropdown').should('have.value', 'gzip');
// # Navigate to a channel
cy.visit(townsquareLink);
// # Open team menu and click "Team Settings"
cy.uiOpenTeamMenu('Team Settings');
// * Check that the 'Team Settings' modal was opened
cy.get('#teamSettingsModal').should('exist').within(() => {
// clicking on edit button
cy.get('#team_iconEdit').should('be.visible').click();
// verify the settings picture button is visible to click
cy.findByTestId('inputSettingPictureButton').should('be.visible').click();
// * Before uploading the picture the save button must be disabled
cy.uiSaveButton().should('be.disabled');
// # Upload a file on center view
cy.findByTestId('uploadPicture').attachFile(mattermostIcon);
// after uploading the picture the save button must be disabled
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
// # Close the modal
cy.get('#teamSettingsModalLabel').find('button').should('be.visible').click();
});
// Validate that the image is being displayed
cy.get(`#${testTeam.name}TeamButton`).scrollIntoView().within(() => {
cy.findByTestId('teamIconImage').then((imageDiv) => {
const url = imageDiv.css('background-image').split('"')[1];
// # Verify that the response to fetch image is successful and not emmpty
cy.request({url, encoding: 'base64'}).then((response) => {
expect(response.status).to.equal(200);
expect(response.body).to.not.be.null;
});
});
});
});
it('MM-T960 - Web server mode - Webserver Uncompressed', () => {
cy.visit('/admin_console/environment/web_server');
// # Click dropdown to open selection
cy.findByTestId('ServiceSettings.WebserverModedropdown').select('Uncompressed');
// # Click Save button to save the settings
cy.get('#saveSetting').click().wait(TIMEOUTS.ONE_SEC);
// # Navigate to a channel
cy.visit(townsquareLink);
// # Open team menu and click "Team Settings"
cy.uiOpenTeamMenu('Team Settings');
// * Check that the 'Team Settings' modal was opened
cy.get('#teamSettingsModal').should('exist').within(() => {
// clicking on edit button
cy.get('#team_iconEdit').should('be.visible').click();
// verify the settings picture button is visible to click
cy.findByTestId('inputSettingPictureButton').should('be.visible').click();
// * Before uploading the picture the save button must be disabled
cy.uiSaveButton().should('be.disabled');
// # Upload a file on center view
cy.findByTestId('uploadPicture').attachFile(mattermostIcon);
// * After uploading the picture the save button must be disabled
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
// # Close the modal
cy.get('#teamSettingsModalLabel').find('button').should('be.visible').click();
});
// Validate that the image is being displayed
cy.get(`#${testTeam.name}TeamButton`).scrollIntoView().within(() => {
cy.findByTestId('teamIconImage').then((imageDiv) => {
const url = imageDiv.css('background-image').split('"')[1];
// # Verify that the response to fetch image is successful and not emmpty
cy.request({url, encoding: 'base64'}).then((response) => {
expect(response.status).to.equal(200);
expect(response.body).to.not.be.null;
});
});
});
});
it('MM-T961 - Web server mode - Webserver Disabled', () => {
cy.visit('/admin_console/environment/web_server');
// # Click dropdown to open selection
cy.findByTestId('ServiceSettings.WebserverModedropdown').select('Disabled');
// # Click Save button to save the settings
cy.get('#saveSetting').click().wait(TIMEOUTS.ONE_SEC);
// # Navigate to a channel
cy.visit(townsquareLink);
// # Open team menu and click "Team Settings"
cy.uiOpenTeamMenu('Team Settings');
// * Check that the 'Team Settings' modal was opened
cy.get('#teamSettingsModal').should('exist').within(() => {
// clicking on edit button
cy.get('#team_iconEdit').should('be.visible').click();
// verify the settings picture button is visible to click
cy.findByTestId('inputSettingPictureButton').should('be.visible').click();
// * Before uploading the picture the save button must be disabled
cy.uiSaveButton().should('be.disabled');
// # Upload a file on center view
cy.findByTestId('uploadPicture').attachFile(mattermostIcon);
// * After uploading the picture the save button must be disabled
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
// # Close the modal
cy.get('#teamSettingsModalLabel').find('button').should('be.visible').click();
});
// Validate that the image is being displayed
cy.get(`#${testTeam.name}TeamButton`).scrollIntoView().within(() => {
cy.findByTestId('teamIconImage').then((imageDiv) => {
const url = imageDiv.css('background-image').split('"')[1];
// # Verify that the response to fetch image is successful not emmpty
cy.request({url, encoding: 'base64'}).then((response) => {
expect(response.status).to.equal(200);
expect(response.body).to.not.be.null;
});
});
});
});
it('MM-T991 - Database fields can be edited and saved', () => {
cy.visit('/admin_console/environment/database');
const queryTimeoutValue = 100;
const maxOpenConnsValue = 1000;
cy.findByTestId('queryTimeoutinput').clear().type(queryTimeoutValue);
cy.findByTestId('maxOpenConnsinput').clear().type(maxOpenConnsValue);
// # Click Save button to save the settings
cy.get('#saveSetting').click().wait(TIMEOUTS.ONE_SEC);
// Get config again
cy.apiGetConfig().then(({config}) => {
// * Verify the database setting values are saved
expect(config.SqlSettings.QueryTimeout).to.eq(queryTimeoutValue);
expect(config.SqlSettings.MaxOpenConns).to.eq(maxOpenConnsValue);
});
});
it('MM-T993 - Minimum hashtag length at least 2', () => {
const defaultHashtagLength = 3;
const minimumHashtagLength = 2;
function setAndVerifyHashtagLength(length) {
cy.findByTestId('minimumHashtagLengthinput').clear().type(length);
// # Click Save button to save the settings
cy.get('#saveSetting').click({force: true}).wait(TIMEOUTS.ONE_SEC);
// * Verify saved config value
cy.apiGetConfig().then(({config}) => {
const expectedLength = length < minimumHashtagLength ? defaultHashtagLength : length;
expect(config.ServiceSettings.MinimumHashtagLength).to.eq(expectedLength);
});
}
cy.visit('/admin_console/environment/database');
setAndVerifyHashtagLength(4);
setAndVerifyHashtagLength(1);
setAndVerifyHashtagLength(2);
});
it('MM-T995 - Amazon S3 settings', () => {
cy.visit('/admin_console/environment/file_storage');
// # CLick dropdown to open selection
cy.findByTestId('FileSettings.DriverNamedropdown').select('Amazon S3');
// Check that these fields are disabled
cy.findByTestId('FileSettings.Directoryinput').should('be.disabled');
// Check that these fields are not disabled
cy.findByTestId('FileSettings.MaxFileSizenumber').should('not.be.disabled');
cy.findByTestId('FileSettings.AmazonS3Bucketinput').should('not.be.disabled');
cy.findByTestId('FileSettings.AmazonS3PathPrefixinput').should('not.be.disabled');
cy.findByTestId('FileSettings.AmazonS3Regioninput').should('not.be.disabled');
cy.findByTestId('FileSettings.AmazonS3AccessKeyIdinput').should('not.be.disabled');
const amazonS3BucketName = 'test';
const amazonS3PathPrefix = 'test';
cy.findByTestId('FileSettings.MaxFileSizenumber').clear().type(52428800);
cy.findByTestId('FileSettings.AmazonS3Bucketinput').clear().type(amazonS3BucketName);
cy.findByTestId('FileSettings.AmazonS3PathPrefixinput').clear().type(amazonS3PathPrefix);
// # Click Save button to save the settings
cy.get('#saveSetting').click().wait(TIMEOUTS.ONE_SEC);
// Get config again
cy.apiGetConfig().then(({config}) => {
// * Verify the database setting values are saved
expect(config.FileSettings.AmazonS3Bucket).to.eq(amazonS3BucketName);
expect(config.FileSettings.AmazonS3PathPrefix).to.eq(amazonS3PathPrefix);
});
});
it('MM-T996 - Amazon S3 connection error messaging', () => {
cy.visit('/admin_console/environment/file_storage');
// # CLick dropdown to open selection
cy.findByTestId('FileSettings.DriverNamedropdown').select('Amazon S3');
const amazonS3PathPrefix = 'test';
cy.findByTestId('FileSettings.AmazonS3Bucketinput').clear();
cy.findByTestId('FileSettings.AmazonS3PathPrefixinput').scrollIntoView().clear().type(amazonS3PathPrefix);
// # Click Save button to save the settings
cy.get('#saveSetting').click().wait(TIMEOUTS.ONE_SEC);
cy.get('#TestS3Connection').scrollIntoView().should('be.visible').within(() => {
cy.findByText('Test Connection').should('be.visible').click().wait(TIMEOUTS.ONE_SEC);
waitForAlert('Connection unsuccessful: S3 Bucket is required');
});
const amazonS3BucketName = '12';
cy.findByTestId('FileSettings.AmazonS3Bucketinput').clear().type(amazonS3BucketName);
// # Click Save button to save the settings
cy.get('#saveSetting').click().wait(TIMEOUTS.ONE_SEC);
cy.get('#TestS3Connection').scrollIntoView().should('be.visible').within(() => {
cy.findByText('Test Connection').should('be.visible').click().wait(TIMEOUTS.ONE_SEC);
waitForAlert('Connection unsuccessful: Unable to connect to S3. Verify your Amazon S3 connection authorization parameters and authentication settings.');
});
});
it('MM-T963 - Configuration - Purge caches', () => {
cy.visit('/admin_console/environment/web_server');
// # Find the purge all caches button on the page and click it
cy.get('#PurgeButton').scrollIntoView().should('be.visible').within(() => {
cy.findByText('Purge All Caches').should('be.visible').click().wait(TIMEOUTS.ONE_SEC);
});
// # Reload the page
cy.reload();
// * Verify app continues to run successfully by querying for the header
cy.get('.admin-console', {timeout: TIMEOUTS.ONE_MIN}).should('be.visible').within(() => {
cy.get('.admin-console__header').should('be.visible').and('have.text', 'Web Server');
});
});
function waitForAlert(message) {
cy.waitUntil(() => cy.get('.alert').scrollIntoView().should('be.visible').then((alert) => {
return alert[0].innerText === message;
}));
}
});

Просмотреть файл

@@ -0,0 +1,115 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Group: @channels @cloud_only
const professionalPaidFeatures = [
{sidebarName: 'Announcement Banner', featureDiscoveryTitle: 'custom announcement banners'},
{sidebarName: 'AD/LDAP', featureDiscoveryTitle: 'LDAP'},
{sidebarName: 'SAML 2.0', featureDiscoveryTitle: 'SAML'},
{sidebarName: 'OpenID Connect', featureDiscoveryTitle: 'OpenID Connect'},
{sidebarName: 'Guest Access', featureDiscoveryTitle: 'guest accounts'},
];
const enterprisePaidFeatures = [
{sidebarName: 'Groups', featureDiscoveryTitle: 'Active Directory/LDAP groups'},
{sidebarName: 'System Roles', featureDiscoveryTitle: 'controlled access to the System Console'},
{sidebarName: 'Data Retention Policy', featureDiscoveryTitle: 'Create data retention schedules with Mattermost Enterprise'},
{sidebarName: 'Compliance Export', featureDiscoveryTitle: 'Run compliance exports with Mattermost Enterprise'},
{sidebarName: 'Custom Terms of Service', featureDiscoveryTitle: 'Create custom terms of service with Mattermost Enterprise'},
];
function simulateSubscription(subscription) {
cy.intercept('GET', '**/api/v4/cloud/subscription', {
statusCode: 200,
body: subscription,
});
}
function withTrialBefore(trialed) {
cy.intercept('GET', '**/api/v4/trial-license/prev', {
statusCode: 200,
body: {
IsLicensed: trialed,
IsTrial: trialed,
},
});
}
describe('Feature discovery cloud', () => {
beforeEach(() => {
// * Check if server has license for Cloud
cy.apiRequireLicenseForFeature('Cloud');
// # Visit admin console
cy.visit('/admin_console');
});
const testForTrialButton = () => {
cy.get('#start_cloud_trial_btn').should('exist');
cy.get('#start_cloud_trial_btn').contains('Try free for 30 days');
};
const testForUpgradeToProfessionalOption = () => {
cy.get("button[data-testid='featureDiscovery_primaryCallToAction']").should('contain', 'Upgrade now');
cy.get("button[data-testid='featureDiscovery_primaryCallToAction']").click();
cy.get('.PurchaseModal').should('exist');
// *Close PurchaseModal
cy.get('.close-x').click();
};
it('MM-T5120 Cloud | Ensure feature discovery shows option to start trial when no trial has ever been done before', () => {
const subscription = {
id: 'sub_test1',
product_id: 'prod_1',
is_free_trial: 'false',
};
simulateSubscription(subscription);
withTrialBefore('false');
[...professionalPaidFeatures, ...enterprisePaidFeatures].forEach(({sidebarName, featureDiscoveryTitle}) => {
cy.get('li').contains(sidebarName).click();
cy.get("div[data-testid='featureDiscovery_title']").should('contain', featureDiscoveryTitle);
testForTrialButton();
});
});
it('MM-T5121 Cloud | Ensure feature discovery for professional features shows option to upgrade to professional', () => {
const subscription = {
id: 'sub_test1',
product_id: 'prod_1',
is_free_trial: 'false',
trial_end_at: 1,
};
simulateSubscription(subscription);
withTrialBefore('false');
professionalPaidFeatures.forEach(({sidebarName, featureDiscoveryTitle}) => {
cy.get('li').contains(sidebarName).click();
cy.get("div[data-testid='featureDiscovery_title']").should('contain', featureDiscoveryTitle);
testForUpgradeToProfessionalOption();
});
});
it('MM-T5122 Cloud | Ensure feature discovery for enterprise features shows option to contact sales', () => {
const subscription = {
id: 'sub_test1',
product_id: 'prod_1',
is_free_trial: 'false',
trial_end_at: 1,
};
simulateSubscription(subscription);
withTrialBefore('false');
enterprisePaidFeatures.forEach(({sidebarName, featureDiscoveryTitle}) => {
cy.get('li').contains(sidebarName).click();
cy.get("div[data-testid='featureDiscovery_title']").should('contain', featureDiscoveryTitle);
cy.get("button[data-testid='featureDiscovery_primaryCallToAction']").should('contain', 'Contact sales');
});
});
});

Просмотреть файл

@@ -0,0 +1,76 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Group: @channels @system_console @not_cloud
const professionalPaidFeatures = [
{sidebarName: 'Announcement Banner', featureDiscoveryTitle: 'custom announcement banners'},
{sidebarName: 'AD/LDAP', featureDiscoveryTitle: 'LDAP'},
{sidebarName: 'SAML 2.0', featureDiscoveryTitle: 'SAML'},
{sidebarName: 'OpenID Connect', featureDiscoveryTitle: 'OpenID Connect'},
{sidebarName: 'Guest Access', featureDiscoveryTitle: 'guest accounts'},
];
const enterprisePaidFeatures = [
{sidebarName: 'Groups', featureDiscoveryTitle: 'Active Directory/LDAP groups'},
{sidebarName: 'System Roles', featureDiscoveryTitle: 'controlled access to the System Console'},
{sidebarName: 'Data Retention Policy', featureDiscoveryTitle: 'Create data retention schedules with Mattermost Enterprise'},
{sidebarName: 'Compliance Export', featureDiscoveryTitle: 'Run compliance exports with Mattermost Enterprise'},
{sidebarName: 'Custom Terms of Service', featureDiscoveryTitle: 'Create custom terms of service with Mattermost Enterprise'},
];
function withTrialBefore(trialed) {
cy.intercept('GET', '**/api/v4/trial-license/prev', {
statusCode: 200,
body: {
IsLicensed: trialed,
IsTrial: trialed,
},
});
}
describe('Feature discovery self hosted', () => {
beforeEach(() => {
cy.shouldRunOnTeamEdition();
cy.shouldNotRunOnCloudEdition();
// # Visit admin console
cy.visit('/admin_console');
});
it('MM-T5123 Self-Hosted | Ensure feature discovery shows option to start trial when no trial has ever been done before', () => {
withTrialBefore('false');
[...professionalPaidFeatures, ...enterprisePaidFeatures].forEach(({sidebarName, featureDiscoveryTitle}) => {
cy.get('li').contains(sidebarName).click();
cy.get("div[data-testid='featureDiscovery_title']").should('contain', featureDiscoveryTitle);
cy.get('#start_trial_btn').should('exist');
cy.get('#start_trial_btn').contains('Start trial');
});
});
it('MM-T5124 Self-Hosted | Ensure feature discovery for professional features shows option to purchase when a trial has been done before', () => {
withTrialBefore('true');
professionalPaidFeatures.forEach(({sidebarName, featureDiscoveryTitle}) => {
cy.get('li').contains(sidebarName).click();
cy.get("div[data-testid='featureDiscovery_title']").should('contain', featureDiscoveryTitle);
cy.get('#post_trial_purchase_license').should('contain', 'Purchase a license');
cy.get('#post_trial_purchase_license').should('be.enabled');
});
});
it('MM-T5125 Self-Hosted | Ensure feature discovery for enterprise features shows option to contact sales when a trial has been done before', () => {
withTrialBefore('true');
enterprisePaidFeatures.forEach(({sidebarName, featureDiscoveryTitle}) => {
cy.get('li').contains(sidebarName).click();
cy.get("div[data-testid='featureDiscovery_title']").should('contain', featureDiscoveryTitle);
cy.get("button[data-testid='featureDiscovery_primaryCallToAction']").should('contain', 'Contact sales');
cy.get("button[data-testid='featureDiscovery_primaryCallToAction']").should('be.enabled');
});
});
});

Просмотреть файл

@@ -0,0 +1,46 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Group: @channels @te_only @system_console
describe('Feature discovery', () => {
before(() => {
cy.shouldRunOnTeamEdition();
// # Visit admin console
cy.visit('/admin_console');
});
const testCallsToAction = () => {
cy.get("a[data-testid$='CallToAction']").each(($el) => {
cy.wrap($el).should('have.attr', 'href').and('not.eq', '');
cy.wrap($el).should('have.attr', 'target', '_blank');
});
};
it('MM-T4035 - Make Sure All Feature Discoveries Exist', () => {
[
{sidebarName: 'AD/LDAP', featureDiscoveryTitle: 'LDAP'},
{sidebarName: 'SAML 2.0', featureDiscoveryTitle: 'SAML'},
{sidebarName: 'OpenID Connect', featureDiscoveryTitle: 'OpenID Connect'},
{sidebarName: 'Groups', featureDiscoveryTitle: 'Active Directory/LDAP groups'},
{sidebarName: 'Compliance Export', featureDiscoveryTitle: 'compliance exports'},
{sidebarName: 'System Roles', featureDiscoveryTitle: 'controlled access to the System Console'},
{sidebarName: 'Permissions', featureDiscoveryTitle: 'role-based permissions'},
{sidebarName: 'Channels', featureDiscoveryTitle: 'read-only channels'},
{sidebarName: 'Custom Terms of Service', featureDiscoveryTitle: 'custom terms of service'},
{sidebarName: 'Announcement Banner', featureDiscoveryTitle: 'custom announcement banners'},
{sidebarName: 'Guest Access', featureDiscoveryTitle: 'guest accounts'},
].forEach(({sidebarName, featureDiscoveryTitle}) => {
cy.get('li').contains(sidebarName).click();
cy.get("div[data-testid='featureDiscovery_title']").should('contain', featureDiscoveryTitle);
testCallsToAction();
});
});
});

Просмотреть файл

@@ -0,0 +1,56 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console
/**
* Note: This test requires hundreds of deactivated users
* May generate by modifying `make test-data` command at `./mattermost-server/Makefile`
* Should change to `sampledata -w 4 -u 60 --deactivated-users 200`
*/
const perPage = 50;
describe('System Console', () => {
it('SC18512 List pages of inactive users', () => {
// # Go to users management page
cy.visit('/admin_console/user_management/users');
// # Select inactive users
cy.get('#selectUserStatus').select('Inactive');
cy.apiGetAnalytics().then(({analytics}) => {
const inactiveUsers = analytics.filter((d) => {
return d.name === 'inactive_user_count';
}).reduce((_, item) => {
return item.value;
}, 0);
const pages = Math.floor(inactiveUsers / perPage);
const remainder = inactiveUsers % perPage;
Cypress._.forEach(Array(pages), (_, index) => {
if (pages === index) {
// * This is the last page, so:
// * - number of users should match the remainder
// * - no next button since no more inactive users to load
cy.findAllByTestId('userListRow').should('have.length', remainder);
cy.get('#searchableUserListNextBtn').should('not.exist');
} else {
// * There are still next page to load, so:
// * - number of users should match per page
// * - next button is visible
// # Click "Next" to load more.
cy.findAllByTestId('userListRow').should('have.length', perPage);
cy.get('#searchableUserListNextBtn').should('be.visible').click();
}
});
});
});
});

Просмотреть файл

@@ -0,0 +1,80 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console
describe('System Console', () => {
let townSquareUrl;
before(() => {
// # Initialize setup and visit town-square
cy.apiInitSetup().then((out) => {
townSquareUrl = out.townSquareUrl;
});
});
it('MM-T1100 Lock Teammate Name Display for all users', () => {
// # Go to system admin page
cy.visit('/admin_console/site_config/users_and_teams');
// # Set Teammate Name Display dropdown to 'Show nickname if one exists, otherwise show first and last name' and set Lock Teammate Name Display to false
cy.findByTestId('TeamSettings.TeammateNameDisplaydropdown').select('nickname_full_name');
cy.findByTestId('TeamSettings.LockTeammateNameDisplayfalse').click();
// * Assert that there exists a description underneath the Teammate Name Display lock setting with the following text
cy.findByTestId('TeamSettings.LockTeammateNameDisplayhelp-text').contains('When true, disables users\' ability to change settings under Settings > Display > Teammate Name Display.').should('be.visible');
// # Click save button
cy.get('#saveSetting').click();
// # Go to main page
cy.visit(townSquareUrl);
// # Go to Settings > Display
cy.uiOpenSettingsModal('Display');
// # Click Edit button beside Teammate Name Display
cy.get('#name_formatEdit').click();
// # Choose Show first and last name
cy.get('#name_formatFormatC').check();
// # Click Save button to save the settings
cy.uiSave();
// * Assert the description under the Teammate Name Display title has changed to Show first and last name
cy.get('#name_formatDesc').contains('Show first and last name').should('be.visible');
// # Go back to System Admin console page
cy.visit('/admin_console/site_config/users_and_teams');
// # Set Teammate Name Display dropdown to 'Show by username' and set Lock Teammate Name Display to true
cy.findByTestId('TeamSettings.TeammateNameDisplaydropdown').select('username');
cy.findByTestId('TeamSettings.LockTeammateNameDisplaytrue').click();
// # Click save button
cy.uiSave();
// # Go to main page
cy.visit(townSquareUrl);
// # Go to Settings > Display
cy.uiOpenSettingsModal('Display');
// * Assert the description under the Teammate Name Display title has changed to Show username
cy.get('#name_formatDesc').contains('Show username').should('be.visible');
// # Click edit button for Teammate Name Display
cy.get('#name_formatEdit').click();
// * Assert that there exists a description noting that this feature has been locked and can only be changed by system admin
cy.get('#extraInfo').contains('This field is handled through your System Administrator. If you want to change it, you need to do so through your System Administrator.').should('be.visible');
});
});

Просмотреть файл

@@ -0,0 +1,62 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console
describe('Main menu', () => {
before(() => {
cy.visit('/admin_console');
// # Open the hamburger menu
cy.get('button > span[class="menu-icon"]').click();
});
const verifyLink = (text, link) => {
// * Verify link opens in new tab
cy.get('a[href="' + link + '"]').scrollIntoView().should('have.attr', 'target', '_blank');
// * Verify link text matches correct href value
cy.get('a[href="' + link + '"]').contains(text);
};
it('MM-T909 Can switch to team', () => {
// * Verify teams are visible
cy.findByText('Switch to eligendi').should('be.visible');
});
it('MM-T910 Can open Administrators Guide', () => {
cy.apiGetClientLicense().then(({isCloudLicensed}) => {
const guideLink = isCloudLicensed ?
'https://docs.mattermost.com/guides/administration.html#cloud-workspace-management' :
'https://docs.mattermost.com/guides/administration.html';
// * Verify administrator's guide link
verifyLink("Administrator's Guide", guideLink);
});
});
it('MM-T911 Can open Troubleshooting Forum', () => {
// * Verify troubleshooting forum link
verifyLink('Troubleshooting Forum', 'https://forum.mattermost.com/t/how-to-use-the-troubleshooting-forum/150');
});
it('MM-T914 Can log out from system console', () => {
// * Verify log out button is visible
cy.findByText('Log Out').should('be.visible');
});
it('MM-T912 Can open Commercial Support', () => {
// * Verify commercial support
cy.findByText('Commercial Support').click();
cy.get('#commercialSupportModal').should('be.visible');
cy.uiClose();
});
});

Просмотреть файл

@@ -0,0 +1,33 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Group: @channels @system_console @te_only
describe('Settings', () => {
before(() => {
cy.shouldRunOnTeamEdition();
});
it('MM-T1149 Hide mobile-specific settings', () => {
cy.visit('/admin_console/site_config/file_sharing_downloads');
// * Check buttons
cy.get('#adminConsoleWrapper .wrapper--fixed > .admin-console__wrapper').
should('be.visible').
and('contain.text', 'Allow File Sharing');
cy.get('#adminConsoleWrapper .wrapper--fixed > .admin-console__wrapper').
should('be.visible').
and('not.contain.text', 'Allow File Uploads on Mobile');
cy.get('#adminConsoleWrapper .wrapper--fixed > .admin-console__wrapper').
should('be.visible').
and('not.contain.text', 'Allow File Downloads on Mobile');
});
});

Просмотреть файл

@@ -0,0 +1,43 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// - Requires mmctl at fixtures folder
// -> copy ./mmctl/mmctl to ./mattermost-webapp/e2e/cypress/tests/fixtures/mmctl
// Group: @channels @plugin @system_console
describe('System Console > Plugin Management ', () => {
before(() => {
cy.shouldNotRunOnCloudEdition();
});
it('MM-T4742 Plugin Marketplace URL should be disabled if EnableUploads are disabled', () => {
// # Set plugin settings
const newSettings = {
PluginSettings: {
Enable: true,
},
};
cy.apiUpdateConfig(newSettings);
cy.exec('tests/fixtures/mmctl --local config set PluginSettings.EnableUploads false');
cy.visit('/admin_console/plugins/plugin_management');
// * Verify marketplace URL is disabled.
cy.findByTestId('marketplaceUrlinput').should('be.disabled');
cy.exec('tests/fixtures/mmctl --local config set PluginSettings.EnableUploads true');
cy.reload();
// * Verify marketplace URL is enabled.
cy.findByTestId('marketplaceUrlinput').should('be.enabled');
});
});

Просмотреть файл

@@ -0,0 +1,37 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console @not_cloud
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('System Console > Server Logs', () => {
before(() => {
cy.shouldNotRunOnCloudEdition();
// # Visit the system console.
cy.visit('/admin_console');
// # Go to the Server Logs section.
cy.get('#reporting\\/server_logs').click().wait(TIMEOUTS.TWO_SEC);
});
it('MM-T908 Logs - Verify content categories', () => {
// * Verify the banner is showed.
cy.get('.banner__content span').should('not.empty');
// * Verify reload button is showed.
cy.get('.admin-logs-content button span').should('be.visible').and('contain', 'Reload');
// * Verify that server logs are showed correctly.
cy.get('.admin-logs-content div.LogTable').should('be.visible').and('not.empty');
cy.get('.admin-logs-content div.LogTable span').eq(0).should('not.empty');
});
});

Просмотреть файл

@@ -0,0 +1,79 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console @not_cloud
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('System Console > Site Statistics', () => {
let testUser;
before(() => {
cy.shouldNotRunOnCloudEdition();
cy.apiInitSetup({loginAfter: true}).then(({user, offTopicUrl}) => {
// # Login as test user and visit off-topic
testUser = user;
cy.visit(offTopicUrl);
// # Post a message as testUser to make them daily/monthly active
cy.postMessage('New Daily Message');
});
});
it('MM-T903 - Site Statistics > Deactivating a user increments the Daily and Monthly Active Users counts down', () => {
let totalActiveUsersInitial;
let dailyActiveUsersInitial;
let monthlyActiveUsersInitial;
let totalActiveUsersFinal;
let dailyActiveUsersFinal;
let monthlyActiveUsersFinal;
// # Go to admin console
cy.apiAdminLogin();
cy.visit('/admin_console');
// # Go to system analytics
cy.findByTestId('reporting.system_analytics', {timeout: TIMEOUTS.ONE_MIN}).click();
cy.wait(TIMEOUTS.ONE_SEC);
// # Get the number text and turn them into numbers
cy.findByTestId('totalActiveUsers').invoke('text').then((totalActiveText) => {
totalActiveUsersInitial = parseInt(totalActiveText, 10);
});
cy.findByTestId('dailyActiveUsers').invoke('text').then((dailyActiveText) => {
dailyActiveUsersInitial = parseInt(dailyActiveText, 10);
});
cy.findByTestId('monthlyActiveUsers').invoke('text').then((monthlyActiveText) => {
monthlyActiveUsersInitial = parseInt(monthlyActiveText, 10);
// # Deactivate user and reload page and then wait 2 seconds
cy.externalActivateUser(testUser.id, false);
cy.reload();
cy.wait(TIMEOUTS.TWO_SEC);
});
// # Get the numbers required again
cy.findByTestId('totalActiveUsers').invoke('text').then((totalActiveFinalText) => {
totalActiveUsersFinal = parseInt(totalActiveFinalText, 10);
});
cy.findByTestId('dailyActiveUsers').invoke('text').then((dailyActiveFinalText) => {
dailyActiveUsersFinal = parseInt(dailyActiveFinalText, 10);
});
cy.findByTestId('monthlyActiveUsers').invoke('text').then((monthlyActiveFinalText) => {
monthlyActiveUsersFinal = parseInt(monthlyActiveFinalText, 10);
// * Assert that the final number is the initial number minus one
expect(totalActiveUsersFinal).equal(totalActiveUsersInitial - 1);
expect(dailyActiveUsersFinal).equal(dailyActiveUsersInitial - 1);
expect(monthlyActiveUsersFinal).equal(monthlyActiveUsersInitial - 1);
});
});
});

Просмотреть файл

@@ -0,0 +1,46 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @te_only @system_console
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('System Console > Site Statistics', () => {
before(() => {
cy.shouldRunOnTeamEdition();
});
it('MM-T3804 Site Statistics displays expected content categories', () => {
// # Visit site statistics page.
cy.visit('/admin_console/reporting/system_analytics');
// * Check that the header has loaded correctly and contains the expected text.
cy.get('.admin-console__header span', {timeout: TIMEOUTS.ONE_MIN}).should('be.visible').should('contain', 'System Statistics');
// * Check that the rows for the table were generated.
cy.get('.admin-console__content .row').should('have.length', 4);
// * Check that the title content for the stats is as expected.
cy.get('.admin-console__content .row').eq(0).find('.title').eq(0).should('contain', 'Total Active Users');
cy.get('.admin-console__content .row').eq(0).find('.title').eq(1).should('contain', 'Total Teams');
cy.get('.admin-console__content .row').eq(0).find('.title').eq(2).should('contain', 'Total Channels');
cy.get('.admin-console__content .row').eq(0).find('.title').eq(3).should('contain', 'Total Posts');
cy.get('.admin-console__content .row').eq(0).find('.title').eq(4).should('contain', 'Daily Active Users');
cy.get('.admin-console__content .row').eq(0).find('.title').eq(5).should('contain', 'Monthly Active Users');
// * Check that the values for the stats are valid.
cy.get('.admin-console__content .row').eq(0).find('.content').each((el) => {
cy.waitUntil(() => cy.wrap(el).then((content) => {
return content[0].innerText !== 'Loading...';
}));
cy.wrap(el).eq(0).invoke('text').then(parseFloat).should('be.gt', 0);
});
});
});

Просмотреть файл

@@ -0,0 +1,81 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('System Console > Team Statistics', () => {
before(() => {
// # Create team.
cy.apiCreateTeam('mmt906-team', 'mmt906-team').then(({team}) => {
// # Create private channel.
cy.apiCreateChannel(team.id, 'mmt906-ch', 'mmt906-ch', 'P');
// # Visit team statistics page.
cy.visit('/admin_console/reporting/team_statistics');
// # Select created team.
cy.get('select.team-statistics__team-filter__dropdown').select(team.id);
// # Explicit wait to allow stats to get loaded
cy.wait(TIMEOUTS.TWO_SEC);
});
});
it('MM-T906 Team Statistics displays expected content categories', () => {
// * Check that the header has loaded correctly and contains the expected text.
cy.get('.team-statistics__header span').should('be.visible').should('contain', 'Team Statistics for');
// * Check that the rows for the table were generated.
cy.get('.grid-statistics__card').should('have.length', 4);
// * Check that the title content for the stats is as expected.
cy.get('.admin-console__content').eq(0).find('.title').eq(0).should('contain', 'Total Active Users');
cy.get('.admin-console__content').eq(0).find('.title').eq(1).should('contain', 'Public Channels');
cy.get('.admin-console__content').eq(0).find('.title').eq(2).should('contain', 'Private Channels');
cy.get('.admin-console__content').eq(0).find('.title').eq(3).should('contain', 'Total Posts');
cy.get('.total-count.by-day').eq(0).find('.title').should('contain', 'Total Posts');
cy.get('.total-count.by-day').eq(1).find('.title').should('contain', 'Active Users With Posts');
cy.get('.total-count.recent-active-users').eq(0).find('.title').should('contain', 'Recent Active Users');
cy.get('.total-count.recent-active-users').eq(1).find('.title').should('contain', 'Newly Created Users');
// * Check that the values for the stats are valid.
cy.get('.grid-statistics__card').each((el) => {
cy.wrap(el).find('.content').invoke('text').then(parseFloat).should('be.gt', 0);
});
// * Check that the generated tables are not empty.
cy.get('.recent-active-users').find('table').eq(0).should('not.empty');
cy.get('.recent-active-users').find('table').eq(1).should('not.empty');
});
it('MM-T907 - Reporting ➜ Team Statistics - teams listed in alphabetical order', () => {
cy.visit('/admin_console');
cy.get('#reporting\\/team_statistics').click();
cy.wait(TIMEOUTS.ONE_SEC);
// * Verify Teams are listed in alphabetical order, regardless of who created the team
cy.findByTestId('teamFilter').then((el) => {
// # Get the options and append them to a unsorted array (assume unsorted)
const unsortedOptionsText = [];
el[0].childNodes.forEach((child) => unsortedOptionsText.push(child.innerText));
// # Make a copy of the above array and then we sort them
const sortedOptionsText = [...unsortedOptionsText].sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}));
// * Compare the unsorted array and sorted array and if it initially was sorted, these should match
for (let i = 0; i < unsortedOptionsText.length; i++) {
expect(unsortedOptionsText[i]).equal(sortedOptionsText[i]);
}
});
});
});

Просмотреть файл

@@ -0,0 +1,72 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console
import * as TIMEOUTS from '../../../fixtures/timeouts';
import {getAdminAccount} from '../../../support/env';
describe('System Console > User Management > Users', () => {
const admin = getAdminAccount();
it('MM-T940 Users - Revoke all sessions', () => {
// # Login as System Admin
cy.apiAdminLogin();
cy.visit('/admin_console/user_management/users');
// * Verify the presence of Revoke All Sessions button
cy.get('#revoke-all-users').should('be.visible').and('not.have.class', 'btn-danger').click();
// * Verify the confirmation message when users clicks on the Revoke All Sessions button
cy.get('#confirmModalLabel').should('be.visible').and('have.text', 'Revoke all sessions in the system');
cy.get('.modal-body').should('be.visible').and('have.text', 'This action revokes all sessions in the system. All users will be logged out from all devices. Are you sure you want to revoke all sessions?');
cy.get('#confirmModalButton').should('be.visible').and('have.class', 'btn-danger');
// # Click on Cancel button in the confirmation message
cy.get('#cancelModalButton').click();
// * Verify if Confirmation message is closed
cy.get('#confirmModal').should('not.exist');
// * Verify if the Admin's session is still active and user is still in the same page
cy.url().should('contain', '/admin_console/user_management/users');
// * Verify if the Admin's Session is still active and click on it and then confirm
cy.get('#revoke-all-users').should('be.visible').click();
cy.get('#confirmModalButton').click();
// * Verify if Admin User's session is expired and is redirected to login page
cy.url({timeout: TIMEOUTS.HALF_MIN}).should('include', '/login');
cy.get('.login-body-card', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible');
});
it('Verify for Regular Member', () => {
// # Login as System Admin
cy.apiAdminLogin();
// # Create new setup, login as test user and visit town-square
cy.apiInitSetup({loginAfter: true}).then(({team}) => {
cy.visit(`/${team.name}/channels/town-square`);
cy.get('#sidebarItem_off-topic').click({force: true});
// # Issue a Request to Revoke All Sessions as SysAdmin
const baseUrl = Cypress.config('baseUrl');
cy.externalRequest({user: admin, method: 'post', baseUrl, path: 'users/sessions/revoke/all'}).then(() => {
// # Initiate browser activity like visit to town-square
cy.visit(`/${team.name}/channels/town-square`);
// * Verify if the regular member is logged out and redirected to login page
cy.url({timeout: TIMEOUTS.HALF_MIN}).should('include', '/login');
cy.get('.login-body-card', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible');
});
});
});
});

Просмотреть файл

@@ -0,0 +1,72 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @not_cloud @system_console
import * as TIMEOUTS from '../../../fixtures/timeouts';
describe('System console', () => {
before(() => {
cy.shouldNotRunOnCloudEdition();
cy.shouldHavePluginUploadEnabled();
});
it('MM-T898 - Individual plugins can be searched for via the System Console search box', () => {
cy.visit('/admin_console');
// # Enable Plugin Marketplace and Remote Marketplace
cy.apiUpdateConfig({
PluginSettings: {
Enable: true,
EnableMarketplace: true,
EnableRemoteMarketplace: true,
MarketplaceURL: 'https://api.integrations.mattermost.com',
},
});
cy.apiInstallPluginFromUrl('https://github.com/mattermost/mattermost-plugin-antivirus/releases/download/v0.1.2/antivirus-0.1.2.tar.gz', true);
cy.apiInstallPluginFromUrl('https://github.com/mattermost/mattermost-plugin-autolink/releases/download/v1.2.1/mattermost-autolink-1.2.1.tar.gz', true);
cy.apiInstallPluginFromUrl('https://github.com/mattermost/mattermost-plugin-aws-SNS/releases/download/v1.1.0/com.mattermost.aws-sns-1.1.0.tar.gz', true);
// # A bug with the endpoint used for downloading plugins which doesn't send websocket events out so state is not updated
// # Therefore, we visit town-square to update the state of our app then re-visit admin console
cy.visit('ad-1/channels/town-square');
cy.visit('/admin_console');
// # Type first plugin name
cy.get('#adminSidebarFilter').type('Anti');
cy.wait(TIMEOUTS.ONE_SEC);
// * Ensure anti virus plugin is highlighted
cy.get('#plugins\\/plugin_antivirus').then((el) => {
expect(el[0].innerHTML).includes('markjs');
});
// # Type second plugin name
cy.get('#adminSidebarFilter').clear().type('Auto');
cy.wait(TIMEOUTS.ONE_SEC);
// * Ensure autolink plugin is highlighted
cy.get('#plugins\\/plugin_mattermost-autolink').then((el) => {
expect(el[0].innerHTML).includes('markjs');
});
// # Type third plugin name
cy.get('#adminSidebarFilter').clear().type('AWS SN');
cy.wait(TIMEOUTS.ONE_SEC);
// * Ensure aws sns plugin is highlighted
cy.get('#plugins\\/plugin_com\\.mattermost\\.aws-sns').then((el) => {
expect(el[0].innerHTML).includes('markjs');
});
cy.apiUninstallAllPlugins();
});
});

Просмотреть файл

@@ -0,0 +1,139 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Group: @channels @not_cloud @system_console
// # Goes to the System Scheme page as System Admin
const goToSessionLengths = () => {
cy.apiAdminLogin();
cy.visit('/admin_console/environment/session_lengths');
};
// # Wait's until the Saving text becomes Save
const waitUntilConfigSave = () => {
cy.waitUntil(() => cy.get('#saveSetting').then((el) => {
return el[0].innerText === 'Save';
}));
};
// Clicks the save button in the system console page.
// waitUntilConfigSaved: If we need to wait for the save button to go from saving -> save.
// Usually we need to wait unless we are doing this in team override scheme
const saveConfig = (waitUntilConfigSaved = true, clickConfirmationButton = false) => {
// # Save if possible (if previous test ended abruptly all permissions may already be enabled)
cy.get('#saveSetting').then((btn) => {
if (btn.is(':enabled')) {
btn.click();
}
});
if (clickConfirmationButton) {
cy.get('#confirmModalButton').click();
}
if (waitUntilConfigSaved) {
waitUntilConfigSave();
}
};
describe('MM-T2574 Session Lengths', () => {
before(() => {
cy.shouldNotRunOnCloudEdition();
goToSessionLengths();
});
describe('"Extend session length with activity" defaults to true', () => {
it('"Extend session length with activity" radio is checked', () => {
cy.get('#extendSessionLengthWithActivitytrue').check().should('be.checked');
});
});
describe('Setting "Extend session length with activity" to false alters subsequent settings', () => {
before(() => cy.get('#extendSessionLengthWithActivityfalse').check());
it('In team edition, "Session idle timeout" setting should not exist', () => {
cy.get('#sessionIdleTimeoutInMinutesinput').should('not.exist');
});
});
describe('Session Lengths settings should save successfully', () => {
it('Setting "Extend session length with activity" to TRUE should save in UI', () => {
cy.get('#extendSessionLengthWithActivitytrue').check();
saveConfig();
cy.get('#extendSessionLengthWithActivitytrue').should('be.checked');
});
it('Setting "Extend session length with activity" to TRUE is saved in the server configuration', () => {
cy.apiGetConfig().then(({config}) => {
const setting = config.ServiceSettings.ExtendSessionLengthWithActivity;
expect(setting).to.be.true;
});
});
it('Setting "Extend session length with activity" to FALSE should save in UI', () => {
cy.get('#extendSessionLengthWithActivityfalse').check();
saveConfig();
cy.get('#extendSessionLengthWithActivityfalse').should('be.checked');
});
it('Setting "Extend session length with activity" to FALSE is saved in the server configuration', () => {
cy.apiGetConfig().then(({config}) => {
const setting = config.ServiceSettings.ExtendSessionLengthWithActivity;
expect(setting).to.be.false;
});
});
it('Setting "Session Length AD/LDAP and Email (hours)" should save in UI', () => {
cy.findByTestId('sessionLengthWebInHoursinput').
should('have.value', '720').
clear().type('744');
saveConfig();
cy.findByTestId('sessionLengthWebInHoursinput').should('have.value', '744');
});
it('Setting "Session Length AD/LDAP and Email (hours)" should be saved in the server configuration', () => {
cy.apiGetConfig().then(({config}) => {
const setting = config.ServiceSettings.SessionLengthWebInHours;
expect(setting).to.equal(744);
});
});
it('Setting "Session Length Mobile (hours)" should save in UI', () => {
cy.findByTestId('sessionLengthMobileInHoursinput').
should('have.value', '720').
clear().type('744');
saveConfig();
cy.findByTestId('sessionLengthMobileInHoursinput').should('have.value', '744');
});
it('Setting "Session Length Mobile (hours)" should be saved in the server configuration', () => {
cy.apiGetConfig().then(({config}) => {
const setting = config.ServiceSettings.SessionLengthMobileInHours;
expect(setting).to.equal(744);
});
});
it('Setting "Session Length SSO (hours)" should save in UI', () => {
cy.findByTestId('sessionLengthSSOInHoursinput').
should('have.value', '720').
clear().type('744');
saveConfig();
cy.findByTestId('sessionLengthSSOInHoursinput').should('have.value', '744');
});
it('Setting "Session Length SSO (hours)" should be saved in the server configuration', () => {
cy.apiGetConfig().then(({config}) => {
const setting = config.ServiceSettings.SessionLengthSSOInHours;
expect(setting).to.equal(744);
});
});
it('Setting "Session Cache (minutes)" should save in UI', () => {
cy.get('#sessionCacheInMinutes').
should('have.value', '10').
clear().type('11');
saveConfig();
cy.get('#sessionCacheInMinutes').should('have.value', '11');
});
it('Setting "Session Cache (minutes)" should be saved in the server configuration', () => {
cy.apiGetConfig().then(({config}) => {
const setting = config.ServiceSettings.SessionCacheInMinutes;
expect(setting).to.equal(11);
});
});
});
});

Просмотреть файл

@@ -0,0 +1,68 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @te_only @system_console
import * as TIMEOUTS from '../../../fixtures/timeouts';
import {adminConsoleNavigation} from '../../../utils/admin_console';
describe('System Console - Team', () => {
before(() => {
cy.shouldRunOnTeamEdition();
// # Go to system admin then verify admin console URL and header
cy.visit('/admin_console/about/license');
cy.url().should('include', '/admin_console/about/license');
cy.get('.admin-console__header', {timeout: TIMEOUTS.ONE_MIN}).
should('be.visible').
and('have.text', 'Edition and License');
});
const serverType = 'team';
adminConsoleNavigation.forEach((testCase, index) => {
const canNavigate = testCase.type.includes(serverType);
const testTitle = `MM-T4263_${index + 1} ${canNavigate ? 'can' : 'cannot'} navigate to ${testCase.team_header || testCase.header}`;
const testFn = canNavigate ? verifyCanNavigate : verifyCannotNavigate;
it(testTitle, () => {
testFn(testCase);
});
});
});
function verifyCanNavigate(testCase) {
// # Click the link on the sidebar
cy.get('.admin-sidebar', {timeout: TIMEOUTS.ONE_MIN}).
should('be.visible').
findByText(testCase.sidebar).
scrollIntoView().
should('be.visible').
click();
// * Verify that it redirects to the URL and matches with the header
cy.url().should('include', testCase.url);
cy.get('.admin-console__header', {timeout: TIMEOUTS.ONE_MIN}).
should('be.visible').
and(testCase.headerContains ? 'contain' : 'have.text', testCase.team_header || testCase.header);
}
function verifyCannotNavigate(testCase) {
// # Header should not exist in sidebar
cy.get('.admin-sidebar', {timeout: TIMEOUTS.ONE_MIN}).
should('be.visible').
findByText(testCase.sidebar).
should('not.exist');
// # Visit the URL directly
cy.visit(testCase.url);
// * Verify that it redirects to Edition and License page
cy.url().should('include', '/admin_console/about/license');
}

Просмотреть файл

@@ -0,0 +1,145 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @system_console @announcement_banner
import {hexToRgbArray, rgbArrayToString} from '../../../../utils';
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('Announcement Banner', () => {
before(() => {
cy.apiRequireLicense();
});
it('MM-T1128 Announcement Banner - Dismissible banner shows long text truncated', () => {
const bannerEmbedLink = 'http://example.com';
const bannerEndLink = 'http://example.com/the_end';
const bannerText = `Here's an announcement! It has a link: ${bannerEmbedLink}. It's a really long announcement, because we have a lot to say. Be sure to read it all, click the link, then dismiss the banner, and then you can go on to the next test, which will have a shorter announcement. Thank you for reading [to the end](${bannerEndLink}) and have a nice day!`;
const bannerBgColor = '#4378da';
const bannerBgColorRGBArray = hexToRgbArray(bannerBgColor);
const bannerTextColor = '#ffffff';
const bannerTextColorRGBArray = hexToRgbArray(bannerTextColor);
// # Go to announcement banner config page of system console
cy.visit('/admin_console/site_config/announcement_banner');
// # Enable banner if not already enabled
cy.findByTestId('AnnouncementSettings.EnableBanner').
should('be.visible').
within(() => {
cy.findByText('true').
should('be.visible').
click({force: true});
});
// # Enter the long banner text
cy.findByTestId('AnnouncementSettings.BannerText').
should('be.visible').
within(() => {
cy.get('input').
should('be.visible').
clear().
invoke('val', bannerText).
wait(TIMEOUTS.HALF_SEC).
type(' {backspace}{enter}');
});
// # Change the banner background color
cy.findByTestId('AnnouncementSettings.BannerColor').
should('be.visible').
within(() => {
cy.get('input').
should('be.visible').
clear().
type(bannerBgColor);
});
// # Change the banner text color
cy.findByTestId('AnnouncementSettings.BannerTextColor').
should('be.visible').
within(() => {
cy.get('input').
should('be.visible').
clear().
type(bannerTextColor);
});
// # Allow for banner dismissal to true
cy.findByTestId('AnnouncementSettings.AllowBannerDismissal').
should('be.visible').
within(() => {
cy.findByText('true').
should('be.visible').
click({force: true});
});
// # Click on the save button
cy.get('.admin-console').
should('exist').
within(() => {
cy.findByText('Save').should('be.visible').click();
});
// * Verify banner overflow is hidden from viewport
// also verify its background color and text color matches to configuration entered
// and check if the url in the text rendered as anchor tag
cy.get('.announcement-bar').
as('announcementBanner').
should('exist').
and('is.visible').
and('have.css', 'overflow', 'hidden').
and(
'have.css',
'background-color',
rgbArrayToString(bannerBgColorRGBArray),
).
and('have.css', 'color', rgbArrayToString(bannerTextColorRGBArray)).
contains('a', bannerEmbedLink).
should('have.attr', 'href', bannerEmbedLink);
// * Verify only the banner text's first part is visible by ensuring the first link
// is visible but the second link is not
cy.findByText(/Here's an announcement! It has a link: /).
should('be.visible').
within(() => {
cy.get(`a[href="${bannerEmbedLink}"]`).should('be.visible');
cy.get(`a[href="${bannerEndLink}"]`).should('not.be.visible');
});
// # Hover over the banner
cy.get('@announcementBanner').trigger('mouseover');
// * Verify popover is visible
cy.get('#announcement-bar__tooltip').
as('announcementBannerTooltip').
should('be.visible').
within(() => {
// * Verify complete banner is present in the popover
cy.findByText(/Here's an announcement! It has a link: /).should(
'be.visible',
);
cy.findByText(
/. It's a really long announcement, because we have a lot to say. Be sure to read it all, click the link, then dismiss the banner, and then you can go on to the next test, which will have a shorter announcement. Thank you for reading and have a nice day!/,
).should('be.visible');
});
// # Move mouse out of banner area
cy.get('@announcementBanner').trigger('mouseout');
// * Verify the popover is no more visible
cy.get('@announcementBannerTooltip').should('not.exist');
// # Close the banner
cy.get('.announcement-bar__close').should('be.visible').click();
// * Verify the banner is closed
cy.get('@announcementBanner').should('not.exist');
});
});

Просмотреть файл

@@ -0,0 +1,368 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('Customization', () => {
beforeEach(() => {
// # as many of the tests logout the user, ensure it's logged
// in as an admin before each test
cy.apiAdminLogin();
// # Visit customization system console page
cy.visit('/admin_console/site_config/customization');
cy.get('.admin-console__header').should('be.visible').and('have.text', 'Customization');
});
it('MM-T1024 - Can change name and desc with Custom Branding set to false', () => {
// # Make sure necessary field is false
cy.apiUpdateConfig({TeamSettings: {EnableCustomBrand: false}});
// * Verify that setting is visible and matches text content
cy.findByTestId('TeamSettings.SiteNamelabel').scrollIntoView().should('be.visible').and('have.text', 'Site Name:');
// # Update both Site Name and Description to store test values
const siteName = 'Mattermost_Text';
const siteDescription = 'This is a testing Mattermost site';
cy.findByTestId('TeamSettings.SiteNameinput').clear().type(siteName);
cy.findByTestId('TeamSettings.CustomDescriptionTextinput').clear().type(siteDescription);
// # Save setting
saveSetting();
// # Logout
cy.apiLogout();
// * Ensure that the user was redirected to the login page after the logout
cy.url().should('include', '/login');
// * Ensure Site Name and Description are shown the updated values in the login screen
cy.findByRole('link', {name: siteName}).should('be.visible');
cy.get('.login-body-card-title').should('have.text', siteDescription);
});
it('MM-T1025 - Site Name - Product Menu ➜ About and About Modal show custom name', () => {
// * Verify that setting is visible and matches text content
cy.findByTestId('TeamSettings.SiteNamelabel').scrollIntoView().should('be.visible').and('have.text', 'Site Name:');
// # Update Site Name test value
const siteName = "A team's instance";
cy.findByTestId('TeamSettings.SiteNameinput').clear().type(siteName);
// # Save setting
saveSetting();
// # Exit settings
cy.visit('/');
// # Open About Mattermost menu option
cy.uiOpenProductMenu(`About ${siteName}`);
// * Verify in the about modal that the new site name is being shown
cy.get('#aboutModalLabel').should('be.visible').and('have.text', `About ${siteName}`);
});
it('MM-T1026 - Custom Branding - Name character limit', () => {
// * Verify that setting is visible and matches text content
cy.findByTestId('TeamSettings.SiteNamelabel').scrollIntoView().should('be.visible').and('have.text', 'Site Name:');
// Character limit is 30, and Mattermost is exactly 10 characters long
const siteName = 'Mattermost'.repeat(3);
// # Type the maximum amount of characters and then some more
cy.findByTestId('TeamSettings.SiteNameinput').clear().type(siteName + 'something else');
// * Verify that the input field didn't accept more characters than the limit
cy.findByTestId('TeamSettings.SiteNameinput').should('have.value', siteName);
// # Save setting
saveSetting();
// * Verify that the value was saved correctly, without the extra characters
cy.apiGetConfig().then(({config}) => {
expect(config.TeamSettings.SiteName).to.equal(siteName);
});
});
it('MM-T1027 - Custom branding is enabled but no image has been uploaded', () => {
// # Ensure that the brand image is deleted
cy.apiDeleteBrandImage();
cy.reload();
// # Set Enable Custom Branding to true
cy.findByTestId('TeamSettings.EnableCustomBrandtrue').check();
// # Save setting
saveSetting();
// # Logout from the current user
cy.apiLogout();
// * Ensure that the user was redirected to the login page after the logout
cy.url().should('include', '/login');
// * Ensure that the signup is loaded and the img doesn't exist
cy.get('.login-body-custom-branding-image').should('not.exist');
});
it('MM-T1028 - Custom brand image and text - true, and uploaded / updated', () => {
// # Make sure necessary field is false
cy.apiUpdateConfig({TeamSettings: {EnableCustomBrand: false}});
// # Ensure that the brand image is deleted
cy.apiDeleteBrandImage();
cy.reload();
// # Enable custom branding
cy.findByTestId('TeamSettings.EnableCustomBrandtrue').check();
// # Upload the image
cy.findByTestId('CustomBrandImage').should('be.visible').within(() => {
cy.get('input').attachFile('mattermost-icon.png');
});
// * Verify that custom brand image setting is visible and matches text content
cy.findByTestId('TeamSettings.CustomBrandTextlabel').scrollIntoView().should('be.visible').and('have.text', 'Custom Brand Text:');
// # Update custom brand text
const customBrandText = 'This is a custom brand text';
cy.findByTestId('TeamSettings.CustomBrandTextinput').clear().type(customBrandText);
// # Save setting
saveSetting();
// # Logout from the current user
cy.apiLogout();
// * Ensure that the user was redirected to the login page after the logout
cy.url().should('include', '/login');
// * Verify that the image is visible
cy.get('.login-body-custom-branding-image').should('exist').and('be.visible');
cy.get('.login-body-custom-branding-markdown').first().within(() => {
// * Ensure that the custom brand text has been updated
cy.get('p').should('have.text', customBrandText);
});
});
it('MM-T1029 - Custom branding text can render markdown text', () => {
// # Visit emoji system console page
cy.visit('/admin_console/site_config/emoji');
cy.get('.admin-console__header').should('be.visible').and('have.text', 'Emoji');
// # Set Enable Custom Emoji to true
cy.findByTestId('ServiceSettings.EnableCustomEmojitrue').check();
// # Save setting
saveSetting();
// * Visit the add custom emoji page for ad-1
cy.visit('/ad-1/emoji/add');
cy.get('.backstage-header').should('be.visible');
// * Ensure the form is visible
cy.get('.backstage-form').should('be.visible').within(() => {
// # Fill the emoji data
cy.get('input#name').clear().type('yay');
cy.get('input#select-emoji').attachFile('mattermost-icon.png');
// # Save emoji
cy.get('.backstage-form__footer button').click();
});
// # Make sure necessary field is true
cy.apiUpdateConfig({TeamSettings: {EnableCustomBrand: true}});
cy.reload();
// # Visit customization system console page
cy.visit('/admin_console/site_config/customization');
cy.get('.admin-console__header').should('be.visible').and('have.text', 'Customization');
// eslint-disable-next-line no-irregular-whitespace
const customBrandText = `:yay:
:smile:
- This is a bullet point
- This is another bullet point
**This has been bolded**
~~This has been strikethrough~~
*This has been italicized*
[This is a link to mattermost.com](https://mattermost.com)
` + '`This is inline code`'; // eslint-disable-line no-useless-concat
// # Update custom brand text
cy.findByTestId('TeamSettings.CustomBrandTextinput').clear().type(customBrandText);
// # Save setting
saveSetting();
// # Logout
cy.apiLogout();
// * Ensure that the user was redirected to the login page after the logout
cy.url().should('include', '/login');
cy.get('.login-body-custom-branding-markdown').first().scrollIntoView().should('be.visible').within(() => {
// * Ensure custom emoji has been rendered
// ToDo: uncomment after fixing MM-12657
//cy.get('span.emoticon').should('have.attr', 'title', ':yay:');
// * Ensure default emoji has been rendered
cy.get('span.emoticon').should('have.attr', 'title', ':smile:');
// * Ensure the list and two bullets have been rendered
cy.get('ul.markdown__list').should('be.visible').within(() => {
cy.contains('This is a bullet point');
cy.contains('This is another bullet point');
});
// * Find within the paragraph after the list
cy.get('ul+p').should('be.visible').within(() => {
// * Ensure the bold text has been rendered
cy.get('strong').should('be.visible').and('have.text', 'This has been bolded');
// * Ensure the strikethrough text has been rendered
cy.get('del').should('be.visible').and('have.text', 'This has been strikethrough');
// * Ensure the italic text has been rendered
cy.get('em').should('be.visible').and('have.text', 'This has been italicized');
// * Ensure the link has been rendered
cy.get('a.markdown__link').should('be.visible').and('have.text', 'This is a link to mattermost.com').and('have.attr', 'href', 'https://mattermost.com');
// * Ensure the inline code has been rendered
cy.get('.codespan__pre-wrap').should('be.visible').and('have.text', 'This is inline code');
});
});
});
it('MM-T1030 - Custom branding removed - Default site name and description, and brand image and text - false', () => {
// # Make sure necessary field is true
cy.apiUpdateConfig({TeamSettings: {EnableCustomBrand: true}});
cy.reload();
// * Verify that setting is visible and matches text content
cy.findByTestId('TeamSettings.SiteNamelabel').scrollIntoView().should('be.visible').and('have.text', 'Site Name:');
// # Update both Site Name and Description to store default or empty values
const siteName = 'Mattermost';
cy.findByTestId('TeamSettings.SiteNameinput').clear().type(siteName);
cy.findByTestId('TeamSettings.CustomDescriptionTextinput').clear();
// # Remove the brand image
cy.get('button.remove-image__btn').should('be.visible').click();
// # Set Enable Custom Branding to false
cy.findByTestId('TeamSettings.EnableCustomBrandfalse').check();
// # Save setting
saveSetting();
// # Logout
cy.apiLogout();
// * Ensure that the user was redirected to the login page after the logout
cy.url().should('include', '/login');
// * Ensure that the default Site Name is shown in the login screen
cy.get('.header-logo-link svg').should('be.visible');
// * Ensure Description have the default values
cy.findByText('Collaborate with your team in real-time').should('exist').and('be.visible');
// * Ensure that the custom branding img is not visible
cy.get('.login-body-custom-branding-image').should('not.exist');
// * Ensure that the custom branding text is not visible
cy.get('.login-body-custom-branding-markdown').should('not.exist');
});
it('MM-T1282 - Site Name help text matches text field behavior', () => {
// * Verify that the existing Site Name is empty
cy.findByTestId('TeamSettings.SiteNameinput').should('be.empty');
// # Configure a custom Site Name
const siteName = 'MM-T1282';
cy.findByTestId('TeamSettings.SiteNameinput').clear().type(siteName);
// # Save setting
saveSetting();
// # Logout
cy.apiLogout();
// * Ensure that the user was redirected to the login page after the logout
cy.url().should('include', '/login');
// * Ensure that the custom Site Name is shown
cy.findByRole('link', {name: siteName}).should('be.visible');
// # Log back in as an administrator
cy.apiAdminLogin();
// # Visit customization system console page
cy.visit('/admin_console/site_config/customization');
// * Ensure that the 'about' link and modal render the custom Site Name
verifySiteNameInAboutModal(siteName);
// # Empty the Site Name configuration
cy.findByTestId('TeamSettings.SiteNameinput').clear();
// # Save setting
saveSetting();
// # Logout
cy.apiLogout();
// * Ensure that the user was redirected to the login page after the logout
cy.url().should('include', '/login');
// * Ensure that the default Site Name is shown in the login screen
cy.get('.header-logo-link svg').should('be.visible');
// # Log back in as an administrator
cy.apiAdminLogin();
// # Visit customization system console page
cy.visit('/admin_console/site_config/customization');
// * Ensure that the 'about' link and modal render the default Site Name
verifySiteNameInAboutModal('Mattermost');
});
});
function saveSetting() {
// # Click save button, and verify text and visibility
cy.get('#saveSetting').
should('have.text', 'Save').
and('be.enabled').
click().
should('be.disabled').
wait(TIMEOUTS.HALF_SEC);
}
function verifySiteNameInAboutModal(siteName) {
// # Open the hamburger menu
cy.get('button > span[class="menu-icon"]').click();
// # Click to open about modal
cy.findByText(`About ${siteName}`).click();
// * Verify about text is visible
cy.findByText(`About ${siteName}`).should('be.visible');
// # Close the modal
cy.get('div.modal-header button.close').should('exist').click();
}

Просмотреть файл

@@ -0,0 +1,18 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import * as TIMEOUTS from '../../../../fixtures/timeouts';
export function saveSetting() {
// # Click save button, and verify text and visibility
cy.get('#saveSetting').
should('have.text', 'Save').
and('be.enabled').
click().
should('be.disabled').
wait(TIMEOUTS.HALF_SEC);
}
export function backToTeam() {
cy.get('.backstage-navbar__back').click();
}

Просмотреть файл

@@ -0,0 +1,74 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console @enterprise @cloud_only
import * as TIMEOUTS from '../../../../fixtures/timeouts';
import {SupportSettings} from '../../../../utils/constants';
describe('SupportSettings', () => {
before(() => {
// * Check if server has license for Cloud
cy.apiRequireLicenseForFeature('Cloud');
// # As admin, visit default team/channel
cy.visit('/');
});
it('MM-T1031 - Customization Change all links', () => {
// # Open about modal
cy.uiOpenHelpMenu().within(() => {
// * Verify links changed
[
{text: 'Ask the community', link: SupportSettings.ASK_COMMUNITY_LINK},
{text: 'Help resources', link: SupportSettings.HELP_LINK},
{text: 'Report a problem', link: SupportSettings.REPORT_A_PROBLEM_LINK},
{text: 'Keyboard shortcuts'},
].forEach(({text, link}) => {
if (link) {
cy.findByText(text).
parent().
should('have.attr', 'href', link);
} else {
cy.findByText(text);
}
});
});
// # Logout
cy.uiLogout();
// * Verify that the user was redirected to the login page after the logout
cy.url().should('include', '/login');
const guides = [
{text: 'About', link: SupportSettings.ABOUT_LINK},
{text: 'Privacy Policy', link: SupportSettings.PRIVACY_POLICY_LINK},
{text: 'Terms', link: SupportSettings.TERMS_OF_SERVICE_LINK},
{text: 'Help', link: SupportSettings.HELP_LINK},
];
// * Verify that links are correct at login page
guides.forEach((guide) => {
cy.findByText(guide.text).
should('have.attr', 'href', guide.link);
});
// # Visit signup page
cy.findByText('Don\'t have an account?', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').click();
cy.url().should('include', '/signup_user_complete');
// * Verify that links are correct at signup page
guides.forEach((guide) => {
cy.findByText(guide.text).
should('have.attr', 'href', guide.link);
});
});
});

Просмотреть файл

@@ -0,0 +1,217 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console @enterprise @e20_only @not_cloud
import * as TIMEOUTS from '../../../../fixtures/timeouts';
import {TERMS_OF_SERVICE_LINK} from '../../../../utils/constants';
import {backToTeam, saveSetting} from './helper';
describe('SupportSettings', () => {
const tosLink = 'https://github.com/mattermost/platform/blob/master/README.md';
const privacyLink = 'https://github.com/mattermost/platform/blob/master/README.md';
const aboutLink = 'https://mattermost.com/default-about/';
const helpLink = 'https://github.com/mattermost/platform/blob/master/doc/help/README.md';
const problemLink = 'https://forum.mattermost.com/c/trouble-shoot';
before(() => {
cy.shouldNotRunOnCloudEdition();
});
beforeEach(() => {
// # Login as admin and reset config
cy.apiAdminLogin();
cy.apiUpdateConfig();
// # Visit customization system console page
cy.visit('/admin_console/site_config/customization');
});
it('MM-T1031 - Customization Change all links', () => {
// # Edit links in the TOS, Privacy, About, Help, Report fields
cy.findByTestId('SupportSettings.TermsOfServiceLinkinput').clear().type(tosLink);
cy.findByTestId('SupportSettings.PrivacyPolicyLinkinput').clear().type(privacyLink);
cy.findByTestId('SupportSettings.AboutLinkinput').clear().type(aboutLink);
cy.findByTestId('SupportSettings.HelpLinkinput').clear().type(helpLink);
cy.findByTestId('SupportSettings.ReportAProblemLinkinput').clear().type(problemLink);
// # Save setting then back to team view
saveSetting();
backToTeam();
// # Open about modal
cy.uiOpenHelpMenu().within(() => {
// * Verify links changed
[
{text: 'Report a problem', link: problemLink},
{text: 'Help resources', link: helpLink},
].forEach((guide) => {
cy.findByText(guide.text).
parent().
should('have.attr', 'href', guide.link);
});
});
// # Logout
cy.uiLogout();
// * Verify that the user was redirected to the login page after the logout
cy.url().should('include', '/login');
const guides = [
{text: 'About', link: aboutLink},
{text: 'Privacy Policy', link: privacyLink},
{text: 'Terms', link: tosLink},
{text: 'Help', link: helpLink},
];
// * Verify that links are correct at login page
guides.forEach((guide) => {
cy.findByText(guide.text).
should('have.attr', 'href', guide.link);
});
// # Visit signup page
cy.findByText('Don\'t have an account?', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').click();
cy.url().should('include', '/signup_user_complete');
// * Verify that links are correct at signup page
cy.get('.hfroute-footer').scrollIntoView().should('be.visible').within(() => {
guides.forEach((guide) => {
cy.findByText(guide.text).
should('have.attr', 'href', guide.link);
});
});
});
it('MM-T1033 - Customization: Blank TOS link field (login page)', () => {
// # Empty the "terms of services" field
cy.findByTestId('SupportSettings.TermsOfServiceLinkinput').type('any').clear();
// # Save setting
saveSetting();
// # Logout
cy.apiLogout();
// * Verify that the user was redirected to the login page after the logout
cy.url().should('include', '/login');
// * Verify that terms of services link is set to default
cy.findByText('Terms').
should('have.attr', 'href', TERMS_OF_SERVICE_LINK);
});
it('MM-T1036 - Customization: Blank Help and Report a Problem hides options from help menu', () => {
// # Change help and report links to blanks
cy.findByTestId('SupportSettings.HelpLinkinput').type('any').clear();
cy.findByTestId('SupportSettings.ReportAProblemLinkinput').type('any').clear();
// # Save setting and back to team view
saveSetting();
backToTeam();
// * Verify that report link does not exist
cy.uiOpenHelpMenu().within(() => {
cy.get('Report a problem').should('not.exist');
cy.get('Help resources').should('not.exist');
});
});
it('MM-T1038 - Customization App download link - Change to different', () => {
// # Edit links in the support email field
const link = 'some_link';
cy.findByTestId('NativeAppSettings.AppDownloadLinkinput').clear().type(link);
// # Save setting then back to team view
saveSetting();
backToTeam();
// # Open about modal
cy.uiOpenProductMenu().within(() => {
// * Verify that 'Download Apps' has expected link
cy.findByText('Download Apps').
parent().
should('have.attr', 'href', link);
});
});
it('MM-T3289_1 - Help (Ask community link setting)', () => {
// * Verify enable ask community link to be true by default
cy.findByTestId('SupportSettings.EnableAskCommunityLinktrue').should('be.checked');
// * Verify the help text
cy.findByTestId('SupportSettings.EnableAskCommunityLinkhelp-text').should('contain', 'When true, "Ask the community" link appears on the Mattermost user interface and Help Menu, which allows users to join the Mattermost Community to ask questions and help others troubleshoot issues. When false, the link is hidden from users.');
// # Back to team view
backToTeam();
// * Verify that hover shows "Help" text
cy.uiGetHelpButton().
trigger('mouseover', {force: true}).
should('have.attr', 'aria-describedby').
and('equal', 'userGuideHelpTooltip');
cy.uiGetHelpButton().
trigger('mouseout', {force: true}).
should('not.have.attr', 'aria-describedby');
// # Open help menu
cy.uiOpenHelpMenu().within(() => {
// * Verify 4 options shown
cy.findByText('Ask the community');
cy.findByText('Help resources');
cy.findByText('Report a problem');
cy.findByText('Keyboard shortcuts');
// * Verify default link of Ask the community
cy.findByText('Ask the community').
parent().
should('have.attr', 'href', 'https://mattermost.com/pl/default-ask-mattermost-community/');
});
});
it('MM-T3289_2 - Help (Ask community link setting)', () => {
// Disable setting for ask community
cy.findByTestId('SupportSettings.EnableAskCommunityLinkfalse').click();
// Edit help link and report a problem link
cy.findByTestId('SupportSettings.HelpLinkinput').clear().type(helpLink);
cy.findByTestId('SupportSettings.ReportAProblemLinkinput').clear().type(problemLink);
// # Save setting and back to team view
saveSetting();
backToTeam();
// # Open help menu
cy.uiOpenHelpMenu().within(() => {
// * Verify 3 options shown
cy.findByText('Help resources');
cy.findByText('Report a problem');
cy.findByText('Keyboard shortcuts');
// * Verify help link has changed
cy.findByText('Help resources').
parent().
should('have.attr', 'href', helpLink);
// * Verify report a problem link has changed
cy.findByText('Report a problem').
parent().
should('have.attr', 'href', problemLink);
// # Click on keyboard shortcuts
cy.findByText('Keyboard shortcuts').click();
});
// * Verify link opens keyboard shortcuts modal
cy.findAllByRole('dialog', 'Keyboard shortcuts');
});
});

Просмотреть файл

@@ -0,0 +1,108 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @not_cloud @system_console
import {
FixedPublicLinks,
} from '../../../../utils';
import * as TIMEOUTS from '../../../../fixtures/timeouts';
import {backToTeam, saveSetting} from './helper';
describe('SupportSettings', () => {
const tosLink = 'https://github.com/mattermost/platform/blob/master/README.md';
const privacyLink = 'https://github.com/mattermost/platform/blob/master/README.md';
let siteName;
before(() => {
cy.shouldNotRunOnCloudEdition();
cy.apiGetConfig().then(({config}) => {
siteName = config.TeamSettings.SiteName;
});
});
beforeEach(() => {
cy.apiAdminLogin();
cy.apiUpdateConfig();
// # Visit customization system console page
cy.visit('/admin_console/site_config/customization');
});
it('MM-T1032 - Customization: Custom Terms and Privacy links in the About modal', () => {
// # Edit links in the TOS and Privacy fields
cy.findByTestId('SupportSettings.TermsOfServiceLinkinput').clear().type(tosLink);
cy.findByTestId('SupportSettings.PrivacyPolicyLinkinput').clear().type(privacyLink);
// # Save setting then back to team view
saveSetting();
backToTeam();
// # Open about modal
cy.uiOpenProductMenu(`About ${siteName}`);
// * Verify that links do not change and they open to default pages
cy.get('#tosLink').should('contain', 'Terms of Use').and('have.attr', 'href').and('equal', FixedPublicLinks.TermsOfService);
cy.get('#privacyLink').should('contain', 'Privacy Policy').and('have.attr', 'href').and('equal', FixedPublicLinks.PrivacyPolicy);
});
it('MM-T1034 - Customization: Blank TOS link field (About modal)', () => {
// # Empty the "terms of services" field
cy.findByTestId('SupportSettings.TermsOfServiceLinkinput').type('any').clear();
// # Save setting then back to team view
saveSetting();
backToTeam();
// # Open about modal
cy.uiOpenProductMenu(`About ${siteName}`);
// * Verify that tos link is set to default
cy.get('#tosLink').should('contain', 'Terms of Use').and('have.attr', 'href').and('equal', FixedPublicLinks.TermsOfService);
});
it('MM-T1035 - Customization Blank Privacy hides the link', () => {
cy.findByTestId('SupportSettings.PrivacyPolicyLinkinput').clear();
// # Save setting then back to team view
saveSetting();
backToTeam();
// # Open about modal
cy.uiOpenProductMenu(`About ${siteName}`);
// * Verify that tos link is there
cy.get('#tosLink').should('be.visible').and('contain', 'Terms of Use');
// * Verify that privacy link is there
cy.get('#privacyLink').should('contain', 'Privacy Policy').and('have.attr', 'href').and('equal', FixedPublicLinks.PrivacyPolicy);
// # Logout
cy.apiLogout();
// * Verify that the user was redirected to the login page after the logout
cy.url().should('include', '/login');
// * Verify no privacy link
cy.findByText('Privacy Policy').should('not.exist');
// # Visit signup page
cy.findByText('Don\'t have an account?', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').click();
// * Verify no privacy link
cy.get('.hfroute-footer').scrollIntoView().should('be.visible').within(() => {
cy.findByText('Privacy Policy').should('not.exist');
});
});
});

Просмотреть файл

@@ -0,0 +1,43 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @not_cloud @system_console
describe('Site URL', () => {
before(() => {
cy.shouldNotRunOnCloudEdition();
});
it('MM-T3279 - Don\'t allow clearing site URL in System Console', () => {
// # Navigate to System Console -> Environment -> Web Server
cy.visit('/admin_console/environment/web_server');
// # Note the site URL value
cy.findByTestId('ServiceSettings.SiteURLinput').invoke('val').then((originalSiteURLValue) => {
// # Clear the Site URL
cy.findByTestId('ServiceSettings.SiteURLinput').clear();
// # Save
cy.findAllByTestId('saveSetting').click();
cy.waitUntil(() => cy.findAllByTestId('saveSetting').then((el) => {
return el[0].innerText === 'Save';
}));
// * Check that the error message is present
cy.findByTestId('errorMessage').contains('Site URL cannot be cleared.');
// # Reload the page
cy.visit('/admin_console/environment/web_server');
// * Check that the setting is the original value
cy.findByTestId('ServiceSettings.SiteURLinput').should('have.value', originalSiteURLValue);
});
});
});

Просмотреть файл

@@ -0,0 +1,26 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Group: @channels @system_console @te_only
describe('Support Packet Generation', () => {
it('MM-T3817 - Commercial Support Dialog UI - No License', () => {
// # Remove license
cy.apiAdminLogin();
cy.apiDeleteLicense();
// # Go to System Console
cy.visit('/admin_console');
cy.findByRole('button', {name: 'Menu Icon'}).should('exist').click();
// * Make sure the commercial support button takes you to external link
cy.findByRole('link', {name: 'Commercial Support'}).and('have.attr', 'href').and('include', '/commercial-support/');
});
});

Просмотреть файл

@@ -0,0 +1,222 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import moment from 'moment-timezone';
describe('System Console > Site Statistics > True Up Review', () => {
before(() => {
cy.apiInitSetup();
cy.apiRequireLicense();
cy.apiGetConfig().then(({config}) => {
const originalConfig = config;
const newConfig = {
...originalConfig,
LogSettings: {
...originalConfig.LogSettings,
EnableDiagnostics: false,
},
};
cy.apiUpdateConfig(newConfig);
});
});
it('cloud instances should not see true up review sections', () => {
cy.apiAdminLogin();
cy.apiRequireLicense('cloud');
// # Go to team statistics
cy.visit('/admin_console/reporting/team_statistics');
cy.findByText('True Up Review').should('not.exist');
// # Go to site statistics
cy.visit('/admin_console/reporting/system_analytics');
cy.findByText('True Up Review').should('not.exist');
});
it('starter instances should not see true up review sections', () => {
cy.apiAdminLogin();
cy.apiRequireLicense('starter');
// # Go to team statistics
cy.visit('/admin_console/reporting/team_statistics');
cy.findByText('True Up Review').should('not.exist');
// # Go to site statistics
cy.visit('/admin_console/reporting/system_analytics');
cy.findByText('True Up Review').should('not.exist');
});
it('non-admin users do no see the true up review sections', () => {
// # Go to team statistics
cy.visit('/admin_console/reporting/team_statistics');
cy.findByText('True Up Review').should('not.exist');
// # Go to site statistics
cy.visit('/admin_console/reporting/system_analytics');
cy.findByText('True Up Review').should('not.exist');
});
it('true up review exists in each statistics section', () => {
// # Log in as admin
cy.apiAdminLogin();
const dueDate = moment().add(1, 'day').unix();
cy.intercept('GET', '**/api/v4/license/review/status', {statusCode: 200, body: {complete: false, due_date: dueDate}}).as('reviewStatus');
// # Go to team statistics
cy.visit('/admin_console/reporting/team_statistics');
cy.findByText('True Up Review').should('exist');
// # Go to site statistics
cy.visit('/admin_console/reporting/system_analytics');
cy.findByText('True Up Review').should('exist');
});
it('non air-gapped instances can submit a true up review request', () => {
// # Log in as admin
cy.apiAdminLogin();
const dueDate = moment().add(1, 'day').unix();
cy.intercept('GET', '**/api/v4/hosted_customer/signup_available', {statusCode: 200, body: {status: 'OK'}}).as('reviewRequest');
cy.intercept('GET', '**/api/v4/license/review/status', {statusCode: 200, body: {complete: false, due_date: dueDate}}).as('reviewStatus');
cy.intercept('POST', '**/api/v4/license/review', {statusCode: 200, body: {status: 'OK'}}).as('reviewRequest');
// # Go to team statistics
cy.visit('/admin_console/reporting/team_statistics');
cy.findByText('True Up Review').should('exist');
cy.findByText('Share to Mattermost').should('exist').click();
cy.wait('@reviewRequest');
cy.findByText('Success!').should('exist');
});
it('air-gapped instances can submit a true up review request (for bundle download)', () => {
// # Log in as admin
cy.apiAdminLogin();
const dueDate = moment().add(1, 'day').unix();
cy.intercept('GET', '**/api/v4/hosted_customer/signup_available', {statusCode: 200, body: {status: 'OK'}}).as('reviewRequest');
cy.intercept('POST', '**/api/v4/license/review', {statusCode: 200, body: {status: 'OK'}}).as('reviewRequest');
cy.intercept('GET', '**/api/v4/license/review/status', {statusCode: 200, body: {complete: false, due_date: dueDate}}).as('reviewStatus');
// # Go to team statistics
cy.visit('/admin_console/reporting/team_statistics');
cy.findByText('True Up Review').should('exist');
cy.findByText('Share to Mattermost').should('exist').click();
cy.wait('@reviewRequest');
cy.findByText('Success!').should('exist');
});
it('error state visible when review request fails', () => {
// # Log in as admin
cy.apiAdminLogin();
cy.apiRequireLicense();
const dueDate = moment().add(1, 'day').unix();
cy.intercept('GET', '**/api/v4/hosted_customer/signup_available', {statusCode: 200, body: {status: 'OK'}}).as('reviewRequest');
cy.intercept('GET', '**/api/v4/license/review/status', {statusCode: 200, body: {complete: false, due_date: dueDate}}).as('reviewStatus');
cy.intercept('POST', '**/api/v4/license/review', {statusCode: 500}).as('reviewRequest');
// # Go to team statistics
cy.visit('/admin_console/reporting/team_statistics');
cy.findByText('True Up Review').should('exist');
cy.findByText('Share to Mattermost').should('exist').click();
cy.wait('@reviewRequest');
cy.findByText('There was an issue sending your True Up Review. Please try again.').should('exist');
});
it('panel should not be present if true up review is already complete', () => {
// # Log in as admin
cy.apiAdminLogin();
cy.apiRequireLicense();
const dueDate = moment().add(1, 'day').unix();
cy.intercept('GET', '**/api/v4/hosted_customer/signup_available', {statusCode: 200, body: {status: 'OK'}}).as('reviewRequest');
cy.intercept('GET', '**/api/v4/license/review/status', {statusCode: 200, body: {complete: true, due_date: dueDate}}).as('reviewStatus');
// # Go to team statistics
cy.visit('/admin_console/reporting/team_statistics');
cy.findByText('True Up Review').should('not.exist');
// # Go to site statistics
cy.visit('/admin_console/reporting/system_analytics');
cy.findByText('True Up Review').should('not.exist');
});
it('panel should not be present if current date is not within the due date window', () => {
// # Log in as admin
cy.apiAdminLogin();
cy.apiRequireLicense();
const dueDate = moment().add(20, 'day').unix();
cy.intercept('GET', '**/api/v4/hosted_customer/signup_available', {statusCode: 200, body: {status: 'OK'}}).as('reviewRequest');
cy.intercept('GET', '**/api/v4/license/review/status', {statusCode: 200, body: {complete: true, due_date: dueDate}}).as('reviewStatus');
// # Go to team statistics
cy.visit('/admin_console/reporting/team_statistics');
cy.findByText('True Up Review').should('not.exist');
// # Go to site statistics
cy.visit('/admin_console/reporting/system_analytics');
cy.findByText('True Up Review').should('not.exist');
});
it('panel should not be present if current date is not within the due date window', () => {
// # Log in as admin
cy.apiAdminLogin();
cy.apiRequireLicense();
const dueDate = moment().add(20, 'day').unix();
cy.intercept('GET', '**/api/v4/hosted_customer/signup_available', {statusCode: 200, body: {status: 'OK'}}).as('reviewRequest');
cy.intercept('GET', '**/api/v4/license/review/status', {statusCode: 200, body: {complete: true, due_date: dueDate}}).as('reviewStatus');
// # Go to team statistics
cy.visit('/admin_console/reporting/team_statistics');
cy.findByText('True Up Review').should('not.exist');
// # Go to site statistics
cy.visit('/admin_console/reporting/system_analytics');
cy.findByText('True Up Review').should('not.exist');
});
it('panel should not be present if telemetry is enabled', () => {
// # Log in as admin
cy.apiAdminLogin();
cy.apiRequireLicense();
cy.apiGetConfig().then(({config}) => {
const originalConfig = config;
const newConfig = {
...originalConfig,
LogSettings: {
...originalConfig.LogSettings,
EnableDiagnostics: true,
},
};
cy.apiUpdateConfig(newConfig);
});
const dueDate = moment().add(1, 'day').unix();
cy.intercept('GET', '**/api/v4/hosted_customer/signup_available', {statusCode: 200, body: {status: 'OK'}}).as('reviewRequest');
cy.intercept('GET', '**/api/v4/license/review/status', {statusCode: 200, body: {complete: true, due_date: dueDate}}).as('reviewStatus');
// # Go to team statistics
cy.visit('/admin_console/reporting/team_statistics');
cy.findByText('True Up Review').should('not.exist');
// # Go to site statistics
cy.visit('/admin_console/reporting/system_analytics');
cy.findByText('True Up Review').should('not.exist');
});
});

Просмотреть файл

@@ -0,0 +1,52 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @customization
describe('Customization', () => {
it('MM-T5379 - Should match title and custom description in root html', () => {
const defaultTitle = 'Mattermost';
const defaultDescription = 'Log in';
const customTitle = 'Custom site name';
const customDescription = 'Custom description';
// # Log out and visit login page
cy.apiLogout();
cy.visit('/login');
// * Verify that the head tag contains default title and without og:description
cy.get('head').find('title').should('have.text', defaultTitle);
cy.get('head').get('meta[property="og:description"]').should('not.exist');
// * Verify that the header contains default logo/image
cy.get('.header-logo-link').should('have.text', '').and('have.attr', 'href', '/').find('svg').should('be.visible');
// * Verify that login card contains default description
cy.get('.login-body-card-title').should('be.visible').and('have.text', defaultDescription);
// # Update the site name and custom description
cy.apiAdminLogin();
cy.apiUpdateConfig({TeamSettings: {SiteName: customTitle, CustomDescriptionText: customDescription}});
// # Log out and visit login page
cy.apiLogout();
cy.visit('');
// * Verify that the head tag contains custom title and description
cy.get('head').find('title').should('have.text', customTitle);
cy.get('head').get('meta[property="og:description"]').should('have.attr', 'content', customDescription);
// * Verify that the header contains custom title
cy.get('.header-logo-link').should('have.text', customTitle).and('have.attr', 'href', '/');
// * Verify that login card contains custom description
cy.get('.login-body-card-title').should('be.visible').and('have.text', customDescription);
});
});

Просмотреть файл

@@ -0,0 +1,242 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @not_cloud @system_console
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('Customization', () => {
let origConfig;
before(() => {
cy.shouldNotRunOnCloudEdition();
// Get config
cy.apiGetConfig().then(({config}) => {
origConfig = config;
});
// # Visit customization system console page
cy.visit('/admin_console/site_config/customization');
cy.get('.admin-console__header').should('be.visible').and('have.text', 'Customization');
});
it('MM-T1214 - Can change Report a Problem Link setting', () => {
// * Verify Report a Problem link label is visible and matches the text
cy.findByTestId('SupportSettings.ReportAProblemLinklabel').scrollIntoView().should('be.visible').and('have.text', 'Report a Problem Link:');
// * Verify Report a Problem link input box has default value. The default value depends on the setup before running the test.
cy.findByTestId('SupportSettings.ReportAProblemLinkinput').should('have.value', origConfig.SupportSettings.ReportAProblemLink);
// * Verify Report a Problem link help text is visible and matches the text
cy.findByTestId('SupportSettings.ReportAProblemLinkhelp-text').find('span').should('be.visible').and('have.text', 'The URL for the Report a Problem link in the Help Menu. If this field is empty, the link is removed from the Help Menu.');
// # Enter a problem link
const reportAProblemLink = 'https://mattermost.com/default-report-a-problem/';
cy.findByTestId('SupportSettings.ReportAProblemLinkinput').clear().type(reportAProblemLink);
// # Save setting
saveSetting();
// Get config again
cy.apiGetConfig().then(({config}) => {
// * Verify the Report a Problem link is saved, directly via REST API
expect(config.SupportSettings.ReportAProblemLink).to.eq(reportAProblemLink);
});
});
it('MM-T1212 - Can change Privacy Policy Link setting', () => {
// * Verify that setting is visible and matches text content
cy.findByTestId('SupportSettings.PrivacyPolicyLinklabel').scrollIntoView().should('be.visible').and('have.text', 'Privacy Policy Link:');
// * Verify that help setting is visible and matches text content
const content = 'The URL for the Privacy link on the login and sign-up pages. If this field is empty, the Privacy link is hidden from users.';
cy.findByTestId('SupportSettings.PrivacyPolicyLinkhelp-text').scrollIntoView().find('span').should('be.visible').and('have.text', content);
// * Verify the input box visible and has default value
cy.findByTestId('SupportSettings.PrivacyPolicyLinkinput').scrollIntoView().should('have.value', origConfig.SupportSettings.PrivacyPolicyLink).and('be.visible');
// # Fill input field with value
const stringToSave = 'https://some.com';
cy.findByTestId('SupportSettings.PrivacyPolicyLinkinput').clear().type(stringToSave);
// # Save setting
saveSetting();
// * Verify that the value is save, directly via REST API
cy.apiGetConfig().then(({config}) => {
expect(config.SupportSettings.PrivacyPolicyLink).to.equal(stringToSave);
});
});
it('MM-T1216 Can change Android App Download Link setting', () => {
// # Scroll Android App Download Link section into view and verify that it's visible
cy.findByTestId('NativeAppSettings.AndroidAppDownloadLink').scrollIntoView().should('be.visible');
// * Verify that Android App Download Link label is visible and matches text content
cy.findByTestId('NativeAppSettings.AndroidAppDownloadLinklabel').should('be.visible').and('have.text', 'Android App Download Link:');
// * Verify the Android App Download Link input box has default value. The default value depends on the setup before running the test.
cy.findByTestId('NativeAppSettings.AndroidAppDownloadLinkinput').should('have.value', origConfig.NativeAppSettings.AndroidAppDownloadLink);
// * Verify that the help text is visible and matches text content
cy.findByTestId('NativeAppSettings.AndroidAppDownloadLinkhelp-text').find('span').should('be.visible').and('have.text', 'Add a link to download the Android app. Users who access the site on a mobile web browser will be prompted with a page giving them the option to download the app. Leave this field blank to prevent the page from appearing.');
const newAndroidAppDownloadLink = 'https://example.com/android-app/';
// * Verify that set value is visible and matches text
cy.findByTestId('NativeAppSettings.AndroidAppDownloadLinkinput').clear().type(newAndroidAppDownloadLink).should('have.value', newAndroidAppDownloadLink);
// # Save setting
saveSetting();
// * Verify that the config is correctly saved in the server
cy.apiGetConfig().then(({config}) => {
expect(config.NativeAppSettings.AndroidAppDownloadLink).to.equal(newAndroidAppDownloadLink);
});
});
it('MM-T1217 Can change iOS App Download Link setting', () => {
// # Scroll iOS App Download Link section into view and verify that it's visible
cy.findByTestId('NativeAppSettings.IosAppDownloadLink').scrollIntoView().should('be.visible');
// * Verify that iOS App Download Link label is visible and matches text content
cy.findByTestId('NativeAppSettings.IosAppDownloadLinklabel').should('be.visible').and('have.text', 'iOS App Download Link:');
// * Verify the iOS App Download Link input box has default value. The default value depends on the setup before running the test.
cy.findByTestId('NativeAppSettings.IosAppDownloadLinkinput').should('have.value', origConfig.NativeAppSettings.IosAppDownloadLink);
// * Verify that the help text is visible and matches text content
cy.findByTestId('NativeAppSettings.IosAppDownloadLinkhelp-text').find('span').should('be.visible').and('have.text', 'Add a link to download the iOS app. Users who access the site on a mobile web browser will be prompted with a page giving them the option to download the app. Leave this field blank to prevent the page from appearing.');
const newIosAppDownloadLink = 'https://example.com/iOS-app/';
// * Verify that set value is visible and matches text
cy.findByTestId('NativeAppSettings.IosAppDownloadLinkinput').clear().type(newIosAppDownloadLink).should('have.value', newIosAppDownloadLink);
// # Save setting
saveSetting();
// * Verify that the config is correctly saved in the server
cy.apiGetConfig().then(({config}) => {
expect(config.NativeAppSettings.IosAppDownloadLink).to.equal(newIosAppDownloadLink);
});
});
it('MM-T1215 - Can change Mattermost Apps Download Page Link setting', () => {
// * Verify Mattermost Apps Download Page Link's setting name is visible and matches the text
cy.findByTestId('NativeAppSettings.AppDownloadLinklabel').scrollIntoView().should('be.visible').and('have.text', 'Mattermost Apps Download Page Link:');
// * Verify the Mattermost Apps Download Page Link input box has default value. The default value depends on the setup before running the test.
cy.findByTestId('NativeAppSettings.AppDownloadLinkinput').should('have.value', origConfig.NativeAppSettings.AppDownloadLink);
// * Verify the site name's help text is visible and matches the text
cy.findByTestId('NativeAppSettings.AppDownloadLinkhelp-text').find('span').should('be.visible').and('have.text', 'Add a link to a download page for the Mattermost apps. When a link is present, an option to "Download Mattermost Apps" will be added in the Product Menu so users can find the download page. Leave this field blank to hide the option from the Product Menu.');
// # Enter new App download link
const newAppDownloadLink = 'https://example.com/app-download-link/';
cy.findByTestId('NativeAppSettings.AppDownloadLinkinput').clear().type(newAppDownloadLink);
// # Save setting
saveSetting();
// Get config again
cy.apiGetConfig().then(({config}) => {
// * Verify the App download link is saved, directly via REST API
expect(config.NativeAppSettings.AppDownloadLink).to.eq(newAppDownloadLink);
});
});
it('MM-T1209 - Can change Help Link setting', () => {
// * Verify that setting is visible and matches text content
const contents = ['The URL for the Help link on the Mattermost login page, sign-up pages, and Help Menu. If this field is empty, the Help link is hidden from users.'];
cy.findByTestId('SupportSettings.HelpLinklabel').scrollIntoView().should('be.visible').and('have.text', 'Help Link:');
// * Verify that help setting is visible and matches text content
cy.findByTestId('SupportSettings.HelpLinkhelp-text').scrollIntoView().find('span').should('be.visible').and('have.text', contents[0]);
// * Verify the input box visible and has default value
cy.findByTestId('SupportSettings.HelpLinkinput').scrollIntoView().should('have.value', origConfig.SupportSettings.HelpLink).and('be.visible');
// # Fill input field with value
const stringToSave = 'https://some.com';
cy.findByTestId('SupportSettings.HelpLinkinput').clear().type(stringToSave);
// # Save setting
saveSetting();
// * Verify that the value is save, directly via REST API
cy.apiGetConfig().then(({config}) => {
expect(config.SupportSettings.HelpLink).to.equal(stringToSave);
});
});
it('MM-T1213 Can change About Link setting', () => {
const newAboutLink = 'https://mattermost.com/';
// * Verify that setting is visible and has the correct label text
cy.findByTestId('SupportSettings.AboutLinklabel').scrollIntoView().should('be.visible').and('have.text', 'About Link:');
// * Verify that the help text is visible and matches text content
cy.findByTestId('SupportSettings.AboutLinkhelp-text').should('be.visible').and('have.text', 'The URL for the About link on the Mattermost login and sign-up pages. If this field is empty, the About link is hidden from users.');
// * Verify that the existing is visible and has default value
cy.findByTestId('SupportSettings.AboutLinkinput').should('be.visible').and('have.value', origConfig.SupportSettings.AboutLink);
// # Clear existing about link and type the new about link
cy.findByTestId('SupportSettings.AboutLinkinput').clear().type(newAboutLink);
// # Save setting
saveSetting();
cy.apiGetConfig().then(({config}) => {
expect(config.SupportSettings.AboutLink).to.equal(newAboutLink);
});
});
it('MM-T1211 - Can change Terms of Use Link setting', () => {
// * Verify site name's setting name for is visible and matches the text
cy.findByTestId('SupportSettings.TermsOfServiceLinklabel').scrollIntoView().should('be.visible').and('have.text', 'Terms of Use Link:');
// * Verify the site name input box has default value. The default value depends on the setup before running the test.
cy.findByTestId('SupportSettings.TermsOfServiceLinkinput').should('have.value', origConfig.SupportSettings.TermsOfServiceLink);
// * Verify the site name's help text is visible and matches the text
cy.findByTestId('SupportSettings.TermsOfServiceLinkhelp-text').find('span').should('be.visible').and('have.text',
'Link to the terms under which users may use your online service. By default, this includes the ' +
'"Mattermost Acceptable Use Policy" explaining the terms under which Mattermost software is ' +
'provided to end users. If you change the default link to add your own terms for using the service you ' +
'provide, your new terms must include a link to the default terms so end users are aware of the Mattermost ' +
'Acceptable Use Policy for Mattermost software.');
// # Enter a new help link
const newValue = 'https://test.com';
cy.findByTestId('SupportSettings.TermsOfServiceLinkinput').clear().type(newValue);
// # Save setting
saveSetting();
// Get config again
cy.apiGetConfig().then(({config}) => {
// * Verify the site name is saved, directly via REST API
expect(config.SupportSettings.TermsOfServiceLink).to.eq(newValue);
});
});
});
function saveSetting() {
// # Click save button, and verify text and visibility
cy.get('#saveSetting').
should('have.text', 'Save').
and('be.enabled').
click().
should('be.disabled').
wait(TIMEOUTS.HALF_SEC);
}

Просмотреть файл

@@ -0,0 +1,180 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('Customization', () => {
let origConfig;
before(() => {
// Get config
cy.apiGetConfig().then(({config}) => {
origConfig = config;
});
// # Visit customization system console page
cy.visit('/admin_console/site_config/customization');
cy.get('.admin-console__header').should('be.visible').and('have.text', 'Customization');
});
it('MM-T1207 - Can change Custom Brand Image setting', () => {
// # Make sure necessary field is false
cy.apiUpdateConfig({TeamSettings: {EnableCustomBrand: false}});
cy.reload();
// # Set Enable Custom Branding to true to be able to upload custom brand image
cy.get('[id="TeamSettings.EnableCustomBrandtrue"]').check();
cy.findByTestId('CustomBrandImage').should('be.visible').within(() => {
// * Verify that setting is visible and matches text content
cy.get('label').should('be.visible').and('have.text', 'Custom Brand Image:');
// * Verify that help setting is visible and matches text content
const contents = 'Customize your user experience by adding a custom image to your login screen. Recommended maximum image size is less than 2 MB.';
cy.get('.help-text').should('be.visible').and('have.text', contents);
// # upload the image
cy.get('input').attachFile('mattermost-icon.png');
});
// # Save setting
saveSetting();
// # Verify that after page reload image exist
cy.reload();
cy.findByTestId('CustomBrandImage').should('be.visible').within(() => {
cy.get('img').should('have.attr', 'src').and('include', '/api/v4/brand/image?t=');
});
});
it('MM-T1204 - Can change Site Name setting', () => {
// * Verify site name's setting name for is visible and matches the text
cy.findByTestId('TeamSettings.SiteNamelabel').scrollIntoView().should('be.visible').and('have.text', 'Site Name:');
// * Verify the site name input box has default value. The default value depends on the setup before running the test.
cy.findByTestId('TeamSettings.SiteNameinput').should('have.value', origConfig.TeamSettings.SiteName);
// * Verify the site name's help text is visible and matches the text
cy.findByTestId('TeamSettings.SiteNamehelp-text').should('be.visible').and('have.text', 'Name of service shown in login screens and UI. When not specified, it defaults to "Mattermost".');
// # Generate and enter a random site name
const siteName = 'New site name';
cy.findByTestId('TeamSettings.SiteNameinput').clear().type(siteName);
// # Save setting
saveSetting();
// Get config again
cy.apiGetConfig().then(({config}) => {
// * Verify the site name is saved, directly via REST API
expect(config.TeamSettings.SiteName).to.eq(siteName);
});
});
it('MM-T1205 - Can change Site Description setting', () => {
// * Verify site description label is visible and matches the text
cy.findByTestId('TeamSettings.CustomDescriptionTextlabel').should('be.visible').and('have.text', 'Site Description: ');
// * Verify the site description input box has default value. The default value depends on the setup before running the test.
cy.findByTestId('TeamSettings.CustomDescriptionTextinput').should('have.value', origConfig.TeamSettings.CustomDescriptionText);
// * Verify the site description help text is visible and matches the text
cy.findByTestId('TeamSettings.CustomDescriptionTexthelp-text').find('span').should('be.visible').and('have.text', 'Displays as a title above the login form. When not specified, the phrase "Log in" is displayed.');
// # Generate and enter a random site description
const siteDescription = 'New site description';
cy.findByTestId('TeamSettings.CustomDescriptionTextinput').clear().type(siteDescription);
// # Save setting
saveSetting();
// Get config again
cy.apiGetConfig().then(({config}) => {
// * Verify the site description is saved, directly via REST API
expect(config.TeamSettings.CustomDescriptionText).to.eq(siteDescription);
});
});
it('MM-T1208 - Can change Custom Brand Text setting', () => {
// * Verify custom brand text label is visible and matches the text
cy.findByTestId('TeamSettings.CustomBrandTextlabel').scrollIntoView().should('be.visible').and('have.text', 'Custom Brand Text:');
// * Verify the custom brand input box has default value. The default value depends on the setup before running the test.
cy.findByTestId('TeamSettings.CustomBrandTextinput').should('have.value', origConfig.TeamSettings.CustomBrandText);
// * Verify the custom brand help text is visible and matches the text
cy.findByTestId('TeamSettings.CustomBrandTexthelp-text').find('span').should('be.visible').and('have.text', 'Text that will appear below your custom brand image on your login screen. Supports Markdown-formatted text. Maximum 500 characters allowed.');
//Enable custom branding
cy.findByTestId('TeamSettings.EnableCustomBrandtrue').check({force: true});
// # Enter a custom brand text
const customBrandText = 'Random brand text';
cy.findByTestId('TeamSettings.CustomBrandTextinput').clear().type(customBrandText);
// # Save setting
saveSetting();
// Get config again
cy.apiGetConfig().then(({config}) => {
// * Verify the custom brand text is saved, directly via REST API
expect(config.TeamSettings.CustomBrandText).to.eq(customBrandText);
});
});
it('MM-T1206 - Can change Enable Custom Branding setting', () => {
// # Make sure necessary field is false
cy.apiUpdateConfig({TeamSettings: {EnableCustomBrand: false}});
cy.reload();
cy.findByTestId('TeamSettings.EnableCustomBrand').should('be.visible').within(() => {
// * Verify that setting is visible and matches text content
cy.get('label:first').should('be.visible').and('have.text', 'Enable Custom Branding: ');
// * Verify that help setting is visible and matches text content
const content = 'Enable custom branding to show an image of your choice, uploaded below, and some help text, written below, on the login page.';
cy.get('.help-text').should('be.visible').and('have.text', content);
// # Set Enable Custom Branding to true
cy.findByTestId('TeamSettings.EnableCustomBrandtrue').check();
});
// # Save setting
saveSetting();
// * Verify that the value is save, directly via REST API
cy.apiGetConfig().then(({config}) => {
expect(config.TeamSettings.EnableCustomBrand).to.equal(true);
});
// # Set Enable Custom Branding to false
cy.findByTestId('TeamSettings.EnableCustomBrandfalse').check();
// # Save setting
saveSetting();
// * Verify that the value is save, directly via REST API
cy.apiGetConfig().then(({config}) => {
expect(config.TeamSettings.EnableCustomBrand).to.equal(false);
});
});
});
function saveSetting() {
// # Click save button, and verify text and visibility
cy.get('#saveSetting').
should('have.text', 'Save').
and('be.enabled').
click().
should('be.disabled').
wait(TIMEOUTS.HALF_SEC);
}

Просмотреть файл

@@ -0,0 +1,63 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @not_cloud @system_console
import {fileSizeToString} from '../../../utils';
describe('Unsaved Changes', () => {
let defaultMaxFileSize;
before(() => {
cy.shouldNotRunOnCloudEdition();
cy.apiGetConfig(true).then(({config}) => {
defaultMaxFileSize = config.MaxFileSize;
});
});
it('MM-T955 Warning leaving changed page without saving: Leave page, discard changes', () => {
// # Make a change on any page.
cy.visit('/admin_console/environment/file_storage');
cy.findByTestId('FileSettings.MaxFileSizenumber').clear().type('150');
// # Click a navigation item in left nav.
cy.findByText('Database').click();
// # When prompted: Yes, discard changes.
cy.get('#confirmModal').should('be.visible');
cy.get('#confirmModalButton').click();
// * Opens other page, changes discarded.
cy.url().should('include', '/environment/database');
cy.visit('/admin_console/environment/file_storage');
cy.findByTestId('FileSettings.MaxFileSizenumber').should('have.value', fileSizeToString(defaultMaxFileSize).replace('MB', ''));
});
it('MM-T956 Warning leaving changed page without saving: Cancel leaving page', () => {
const draftValue = '150';
// # Make a change on any page.
cy.visit('/admin_console/environment/file_storage');
cy.findByTestId('FileSettings.MaxFileSizenumber').clear().type(draftValue);
// # Click a navigation item in left nav.
cy.findByText('Database').click();
// # When prompted: No, cancel.
cy.get('#confirmModal').should('be.visible');
cy.get('#cancelModalButton').click();
// * Stays on current page, changes kept.
cy.url().should('include', '/environment/file_storage');
cy.findByTestId('FileSettings.MaxFileSizenumber').should('have.value', draftValue);
});
});

Просмотреть файл

@@ -0,0 +1,68 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Group: @channels @system_console
import * as MESSAGES from '../../../../fixtures/messages';
describe('System Console > User Management > Deactivation', () => {
let team1;
let otherAdmin;
before(() => {
// # Do initial setup
cy.apiInitSetup().then(({team}) => {
team1 = team;
});
// # Create other sysadmin
cy.apiCreateCustomAdmin().then(({sysadmin}) => {
otherAdmin = sysadmin;
});
});
beforeEach(() => {
// # Login as other admin.
cy.apiLogin(otherAdmin);
// # Visit town-square
cy.visit(`/${team1.name}`);
});
it('MM-T951 Reopened DM shows archived icon in LHS No status indicator in channel header Message box replaced with "You are viewing an archived channel with a deactivated user." in center and RHS - KNOWN ISSUE: MM-42529', () => {
// # Create other user
cy.apiCreateUser({prefix: 'other'}).then(({user}) => {
// # Send a DM to the other user
cy.sendDirectMessageToUser(user, MESSAGES.SMALL);
// # Open RHS
cy.clickPostCommentIcon();
// * Verify status indicator is shown in channel header
cy.get('#channelHeaderDescription .status').should('be.visible');
// # Deactivate other user
cy.apiDeactivateUser(user.id);
// * Verify center channel message box is replace with warning
cy.get('.channel-archived__message').contains('You are viewing an archived channel with a deactivated user. New messages cannot be posted.');
// * Verify RHS message box is replace with warning
cy.get('#rhsContainer .post-create-message').contains('You are viewing an archived channel with a deactivated user. New messages cannot be posted.');
// * Verify status indicator is not shown in channel header
cy.get('#channelHeaderDescription .status').should('not.exist');
// * Verify archived icon is shown in LHS
cy.uiGetLhsSection('DIRECT MESSAGES').
find('.active').should('be.visible').
find('.icon-archive-outline').should('be.visible');
});
});
});

Просмотреть файл

@@ -0,0 +1,65 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console @not_cloud
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('System Console > User Management > Deactivation', () => {
let testUser;
before(() => {
cy.shouldNotRunOnCloudEdition();
// # Do initial setup
cy.apiInitSetup().then(({user}) => {
testUser = user;
});
// # Visit the system console.
cy.visit('/admin_console');
});
it('MM-T947 When deactivating users in the System Console, email address should not disappear', () => {
// # Go to User management / Users tab
cy.findByTestId('user_management.system_users').should('be.visible').click();
// # Search the newly created user in the search box
cy.findByPlaceholderText('Search users').should('be.visible').clear().type(testUser.email).wait(TIMEOUTS.HALF_SEC);
// * Verify that user is listed
cy.findByText(`@${testUser.username}`).should('be.visible');
// # Scan on the first item's row in the list
cy.findByTestId('userListRow').should('be.visible').within(() => {
// * Verify before deactivation email is visible
cy.findByText(testUser.email).should('be.visible');
// # Open the actions menu.
cy.findByText('Member').click().wait(TIMEOUTS.HALF_SEC);
// # Click on deactivate menu button
cy.findByLabelText('User Actions Menu').findByText('Deactivate').click();
});
// # Click confirm deactivate in the modal
cy.get('.a11y__modal').should('exist').and('be.visible').within(() => {
cy.findByText('Deactivate').should('be.visible').click();
});
cy.findByTestId('userListRow').should('be.visible').within(() => {
// * Verify that the user is now inactive
cy.findByText('Inactive').should('be.visible');
// * Verify once again if email is visible
cy.findByText(testUser.email).should('be.visible');
});
});
});

Просмотреть файл

@@ -0,0 +1,145 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console
import * as TIMEOUTS from '../../../../fixtures/timeouts';
import * as MESSAGES from '../../../../fixtures/messages';
describe('System Console > User Management > Deactivation', () => {
let team1;
let otherAdmin;
before(() => {
// # Do initial setup
cy.apiInitSetup().then(({team}) => {
team1 = team;
});
// # Create other sysadmin
cy.apiCreateCustomAdmin().then(({sysadmin}) => {
otherAdmin = sysadmin;
});
});
beforeEach(() => {
// # Login as other admin.
cy.apiLogin(otherAdmin);
// # Visit town-square
cy.visit(`/${team1.name}`);
});
// # Create two users
it('MM-T946 GM: User deactivated in System Console still displays', () => {
cy.apiCreateUser({prefix: 'first'}).then(({user: user1}) => {
cy.apiCreateUser({prefix: 'second'}).then(({user: user2}) => {
const message = MESSAGES.SMALL;
// # Send a GM to them
cy.sendDirectMessageToUsers([user1, user2], message);
// * Verify names on the LHS are still ordered alphabetically
cy.uiGetLhsSection('DIRECT MESSAGES').find('.active').should('contain', user1.username + ', ' + user2.username);
// # Deactivate user 1
cy.apiDeactivateUser(user1.id);
// * Verify names on the LHS are still ordered alphabetically
cy.uiGetLhsSection('DIRECT MESSAGES').find('.active').should('contain', user1.username + ', ' + user2.username);
// # Search for the message send in the GM
cy.uiSearchPosts(message);
// * Verify GM message is returned in RHS
cy.findAllByTestId('search-item-container').
should('be.visible').and('have.length', 1).
eq(0).should('contain', message);
});
});
});
it('MM-T948 DM posts searchable in DM More... and channel switcher DM channel re-openable', () => {
cy.apiCreateUser({prefix: 'other'}).then(({user: other}) => {
// # Open DM
cy.sendDirectMessageToUser(other, MESSAGES.SMALL);
// # Close DM
cy.get('#channelHeaderDropdownIcon').click();
cy.findByText('Close Direct Message').click();
// # Deactivate the user
cy.apiDeactivateUser(other.id);
// # Open Find Channels
cy.uiOpenFindChannels();
// # Type the user name on Channel switcher input
cy.get('#quickSwitchInput').type(other.username).wait(TIMEOUTS.HALF_SEC);
// * Verify user is marked as deactivated
cy.get('[data-testid="' + other.username + '"]').contains('Deactivated');
// # Close Channel Switcher
cy.uiClose();
// # Open DM Modal
cy.uiAddDirectMessage().click().wait(TIMEOUTS.ONE_SEC);
cy.findByRole('dialog', {name: 'Direct Messages'}).should('be.visible').wait(TIMEOUTS.ONE_SEC);
// # Start typing part of a username that matches previously created users
cy.findByRole('textbox', {name: 'Search for people'}).
typeWithForce(other.username).
wait(TIMEOUTS.ONE_SEC);
// * Verify user is marked as deactivated
cy.get('#displayedUserName' + other.username).parent().contains('Deactivated');
// # Click on the user
cy.get('#displayedUserName' + other.username).click();
// * Confirm DM More... Modal is closed
cy.get('#moreDmModal').should('not.exist');
});
});
it('MM-T949 If an active user is selected in DM More... or channel switcher, deactivated users should be shown in the DM more or channel switcher', () => {
// # Create two users
cy.apiCreateUser({prefix: 'first'}).then(({user: user1}) => {
cy.apiCreateUser({prefix: 'second_'}).then(({user: user2}) => {
// # Send a DM to user1 so they show up in the DM modal
cy.sendDirectMessageToUser(user1, MESSAGES.SMALL);
// # Send a DM to user2 so they show up in the DM modal
cy.sendDirectMessageToUser(user2, MESSAGES.SMALL);
// # Deactivate user 2
cy.apiDeactivateUser(user2.id);
// # Open DM Modal
cy.uiAddDirectMessage().click().wait(TIMEOUTS.HALF_SEC);
// # Type the user name of user1 on Channel switcher input
cy.findByRole('textbox', {name: 'Search for people'}).
typeWithForce(user1.username).
wait(TIMEOUTS.ONE_SEC);
// # Click on the user
cy.get('#displayedUserName' + user1.username).click();
// # Type the user name of user2 on Channel switcher input
cy.get('.more-direct-channels #selectItems input').typeWithForce(user2.username).wait(TIMEOUTS.HALF_SEC);
// * Confirm user2 can't be added to the DM
cy.get('#displayedUserName' + user2.username).should('be.visible');
});
});
});
});

Просмотреть файл

@@ -0,0 +1,73 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @not_cloud @system_console
import * as TIMEOUTS from '../../../../fixtures/timeouts';
import * as MESSAGES from '../../../../fixtures/messages';
import {getRandomId} from '../../../../utils';
describe('System Console > User Management > Reactivation', () => {
before(() => {
cy.shouldNotRunOnCloudEdition();
// # Do initial setup
cy.apiInitSetup().then(({team}) => {
// # Visit town-square
cy.visit(`/${team.name}`);
});
});
it('MM-T952 Reactivating a user results in them showing up in the normal spot in the list, without the `Deactivated` label.', () => {
// # Create two users with same random prefix
const id = getRandomId();
cy.apiCreateUser({prefix: id + '_a_'}).then(({user: user1}) => {
cy.apiCreateUser({prefix: id + '_b_'}).then(({user: user2}) => {
// # Send a DM to user1 so they show up in the DM modal
cy.sendDirectMessageToUser(user1, MESSAGES.SMALL);
// # Send a DM to user2 so they show up in the DM modal
cy.sendDirectMessageToUser(user2, MESSAGES.SMALL);
// # Open DM More... Modal
cy.uiAddDirectMessage().click().wait(TIMEOUTS.HALF_SEC);
// # Type the user name of the other user on Channel switcher input
cy.get('.more-direct-channels #selectItems input').typeWithForce(id).wait(TIMEOUTS.HALF_SEC);
// * Verify user 1 is shown first and doesn't have deactivated text
cy.get('#moreDmModal .more-modal__row').siblings().its(0).get('#displayedUserName' + user1.username).parent().should('not.contain', 'Deactivated');
// * Verify user 2 is shown second
cy.get('#moreDmModal .more-modal__row').siblings().its(1).get('#displayedUserName' + user2.username);
// # Deactivate user1
cy.apiDeactivateUser(user1.id).then(() => {
// * Verify user 1 is shown second and does have deactivated text
cy.get('#moreDmModal .more-modal__row').siblings().its(1).get('#displayedUserName' + user1.username).parent().should('contain', 'Deactivated');
// * Verify user 2 is shown first
cy.get('#moreDmModal .more-modal__row').siblings().its(0).get('#displayedUserName' + user2.username);
// # Reactivate user1
cy.apiActivateUser(user1.id).then(() => {
// * Verify user 1 is shown first and doesn't have deactivated text
cy.get('#moreDmModal .more-modal__row').siblings().its(0).get('#displayedUserName' + user1.username).parent().should('not.contain', 'Deactivated');
// * Verify user 2 is shown second
cy.get('#moreDmModal .more-modal__row').siblings().its(1).get('#displayedUserName' + user2.username);
});
});
});
});
});
});

Просмотреть файл

@@ -0,0 +1,248 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('System Console > User Management > Users', () => {
let testUser;
let otherAdmin;
before(() => {
cy.apiInitSetup().then(({user}) => {
testUser = user;
});
// # Create other sysadmin
cy.apiCreateCustomAdmin().then(({sysadmin}) => {
otherAdmin = sysadmin;
});
});
beforeEach(() => {
// # Login as other admin.
cy.apiLogin(otherAdmin);
// # Visit the system console.
cy.visit('/admin_console');
// # Go to the User management/Users section.
cy.findByTestId('user_management.system_users').
click().
wait(TIMEOUTS.ONE_SEC);
});
it('MM-T925 Users - Profile image on User Configuration page is round', () => {
// # Find the created user by entering in the search
cy.findByPlaceholderText('Search users').
should('be.visible').
clear().
type(testUser.email).
wait(TIMEOUTS.HALF_SEC);
// # Click on the searched user name
cy.findByText(`@${testUser.username}`).
should('be.visible').
click({force: true});
// * Verify we landed on the user configuration page
cy.location('pathname').should(
'equal',
`/admin_console/user_management/user/${testUser.id}`,
);
// * Verify that user profile image is round
cy.findByAltText('user profile image').
should('be.visible').
and('have.css', 'border-radius', '50%');
});
it('MM-T932 Users - Change a user\'s password', () => {
// # Search for the user.
cy.get('#searchUsers').type(testUser.email).wait(TIMEOUTS.HALF_SEC);
// # Open the actions menu.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .text-right a').
click().wait(TIMEOUTS.HALF_SEC);
// # Click the Reset Password menu option.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .MenuWrapperAnimation-enter-done').
find('li').eq(3).click().wait(TIMEOUTS.HALF_SEC);
// # Type new password and submit.
cy.get('input[type=password]').type('new' + testUser.password);
cy.get('button[type=submit]').should('contain', 'Reset').click().wait(TIMEOUTS.HALF_SEC);
// # Log out.
cy.apiLogout();
// * Verify that logging in with old password returns an error.
apiLogin(testUser.username, testUser.password).then((response) => {
expect(response.status).to.equal(401);
// * Verify that logging in with the updated password works.
testUser.password = 'new' + testUser.password;
cy.apiLogin(testUser);
// # Log out.
cy.apiLogout();
});
});
it('MM-T933 Users - System admin changes own password - Cancel out of changes', () => {
// # Search for the admin.
cy.get('#searchUsers').type(otherAdmin.username).wait(TIMEOUTS.HALF_SEC);
// # Open the actions menu.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .text-right a').
click().wait(TIMEOUTS.HALF_SEC);
// # Click the Reset Password menu option.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .MenuWrapperAnimation-enter-done').
find('li').eq(2).click().wait(TIMEOUTS.HALF_SEC);
// # Type current password and a new password.
cy.get('input[type=password]').eq(0).type(otherAdmin.password);
cy.get('input[type=password]').eq(1).type('new' + otherAdmin.password);
// # Click the 'Cancel' button.
cy.get('button[type=button].btn.btn-link').should('contain', 'Cancel').click().wait(TIMEOUTS.HALF_SEC);
// # Log out.
cy.apiLogout();
// * Verify that logging in with the old password works.
cy.apiLogin(otherAdmin);
});
it('MM-T934 Users - System admin changes own password - Incorrect old password', () => {
// # Search for the admin.
cy.get('#searchUsers').type(otherAdmin.username).wait(TIMEOUTS.HALF_SEC);
// # Open the actions menu.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .text-right a').
click().wait(TIMEOUTS.HALF_SEC);
// # Click the Reset Password menu option.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .MenuWrapperAnimation-enter-done').
find('li').eq(2).click().wait(TIMEOUTS.HALF_SEC);
// # Type wrong current password and a new password.
cy.get('input[type=password]').eq(0).type('wrong' + otherAdmin.password);
cy.get('input[type=password]').eq(1).type('new' + otherAdmin.password);
// # Click the 'Reset' button.
cy.get('button[type=submit] span').should('contain', 'Reset').click().wait(TIMEOUTS.HALF_SEC);
// * Verify the appropriate error is returned.
cy.get('form.form-horizontal').find('.has-error p.error').should('be.visible').
and('contain', 'The "Current Password" you entered is incorrect. Please check that Caps Lock is off and try again.');
});
it('MM-T935 Users - System admin changes own password - Invalid new password', () => {
// # Search for the admin.
cy.get('#searchUsers').type(otherAdmin.username).wait(TIMEOUTS.HALF_SEC);
// # Open the actions menu.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .text-right a').
click().wait(TIMEOUTS.HALF_SEC);
// # Click the Reset Password menu option.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .MenuWrapperAnimation-enter-done').
find('li').eq(2).click().wait(TIMEOUTS.HALF_SEC);
// # Type current password and a new too short password.
cy.get('input[type=password]').eq(0).type(otherAdmin.password);
cy.get('input[type=password]').eq(1).type('new');
// # Click the 'Reset' button.
cy.get('button[type=submit] span').should('contain', 'Reset').click().wait(TIMEOUTS.HALF_SEC);
// * Verify the appropriate error is returned.
cy.get('form.form-horizontal').find('.has-error p.error').should('be.visible').
and('contain', 'Must be 5-64 characters long.');
});
it('MM-T936 Users - System admin changes own password - Blank fields', () => {
// # Search for the admin.
cy.get('#searchUsers').type(otherAdmin.username).wait(TIMEOUTS.HALF_SEC);
// # Open the actions menu.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .text-right a').
click().wait(TIMEOUTS.HALF_SEC);
// # Click the Reset Password menu option.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .MenuWrapperAnimation-enter-done').
find('li').eq(2).click().wait(TIMEOUTS.HALF_SEC);
// # Click the 'Reset' button.
cy.get('button[type=submit] span').should('contain', 'Reset').click().wait(TIMEOUTS.HALF_SEC);
// * Verify the appropriate error is returned.
cy.get('form.form-horizontal').find('.has-error p.error').should('be.visible').
and('contain', 'Please enter your current password.');
// # Type current password, leave new password blank.
cy.get('input[type=password]').eq(0).type(otherAdmin.password);
// # Click the 'Reset' button.
cy.get('button[type=submit] span').should('contain', 'Reset').click().wait(TIMEOUTS.HALF_SEC);
// * Verify the appropriate error is returned.
cy.get('form.form-horizontal').find('.has-error p.error').should('be.visible').
and('contain', 'Must be 5-64 characters long.');
});
it('MM-T937 Users - System admin changes own password - Successfully changed', () => {
// # Search for the admin.
cy.get('#searchUsers').type(otherAdmin.username).wait(TIMEOUTS.HALF_SEC);
// # Open the actions menu.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .text-right a').
click().wait(TIMEOUTS.HALF_SEC);
// # Click the Reset Password menu option.
cy.get('[data-testid="userListRow"] .more-modal__right .more-modal__actions .MenuWrapper .MenuWrapperAnimation-enter-done').
find('li').eq(2).click().wait(TIMEOUTS.HALF_SEC);
// # Type current and new passwords..
cy.get('input[type=password]').eq(0).type(otherAdmin.password);
cy.get('input[type=password]').eq(1).type('new' + otherAdmin.password);
// # Click the 'Reset' button.
cy.get('button[type=submit] span').should('contain', 'Reset').click().wait(TIMEOUTS.HALF_SEC);
// # Log out.
cy.apiLogout();
// * Verify that logging in with old password returns an error.
apiLogin(otherAdmin.username, otherAdmin.password).then((response) => {
expect(response.status).to.equal(401);
// * Verify that logging in with new password works.
otherAdmin.password = 'new' + otherAdmin.password;
cy.apiLogin(otherAdmin);
// # Reset admin's password to the original.
cy.apiResetPassword('me', otherAdmin.password, otherAdmin.password.substr(3));
});
});
});
function apiLogin(username, password) {
return cy.request({
headers: {'X-Requested-With': 'XMLHttpRequest'},
url: '/api/v4/users/login',
method: 'POST',
body: {login_id: username, password},
failOnStatusCode: false,
});
}

Просмотреть файл

@@ -0,0 +1,181 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console @not_cloud
const TIMEOUTS = require('../../../fixtures/timeouts');
describe('User Management', () => {
let testTeam;
let testChannel;
let sysadmin;
let testUser;
let otherUser;
before(() => {
cy.shouldNotRunOnCloudEdition();
cy.apiInitSetup().then(({team, channel, user}) => {
testChannel = channel;
testTeam = team;
testUser = user;
return cy.apiCreateUser();
}).then(({user: user2}) => {
otherUser = user2;
});
cy.apiAdminLogin().then((res) => {
sysadmin = res.user;
});
});
it('MM-T942 Users - Deactivated user not in drop-down, auto-logged out', () => {
cy.apiLogin(testUser);
// # Create a direct channel between two users
cy.apiCreateDirectChannel([testUser.id, otherUser.id]).then(() => {
// # Visit the channel using the channel name
cy.visit(`/${testTeam.name}/channels/${testUser.id}__${otherUser.id}`);
cy.postMessage('hello');
});
cy.apiLogout().apiAdminLogin();
activateUser(otherUser, false);
cy.apiLogout().wait(TIMEOUTS.FIVE_SEC);
cy.visit('/login');
// # Login as otherUser
cy.get('#input_loginId').should('be.visible').type(otherUser.username);
cy.get('#input_password-input').should('be.visible').type(otherUser.password);
cy.get('#saveSetting').should('be.visible').click();
// * Verify appropriate error message is displayed for deactivated user
cy.findByText('Login failed because your account has been deactivated. Please contact an administrator.').should('exist').and('be.visible');
cy.apiLogin(testUser);
// visit test channel
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
// # Open team menu and click View Members
cy.uiOpenTeamMenu('View Members');
// * Check View Members modal dialog
cy.get('#teamMembersModal').should('be.visible').within(() => {
cy.get('#searchUsersInput').
should('be.visible').
click().
type(otherUser.email, {force: true});
// * Deactivated user does not show up in View Members for teams
cy.findByTestId('noUsersFound');
cy.uiClose();
});
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
// # Click Channel Members
cy.get('.member-rhs__trigger').should('be.visible').click();
// * Deactivated user does not show up in View Members for channels
cy.uiGetRHS().findByText(otherUser.username).should('not.exist');
// * User does show up in DM More menu so that DM channels can be viewed.
cy.uiGetLhsSection('DIRECT MESSAGES').findByText(otherUser.username).should('not.exist');
cy.uiAddDirectMessage().click();
// * Verify that new messages cannot be posted.
cy.get('#moreDmModal').should('be.visible').within(() => {
cy.get('#selectItems input').typeWithForce(otherUser.email + '{enter}').wait(TIMEOUTS.HALF_SEC);
cy.uiGetPostTextBox({exist: false});
});
// # Restore the user.
cy.apiLogout().apiAdminLogin();
activateUser(otherUser, true);
});
it('MM-T943 Users - Deactivate a user - DM, GM in LHS (not actively viewing DM in another window)', () => {
cy.apiLogin(testUser);
// # Open a DM with a user you want to deactivate, post a message
cy.apiCreateDirectChannel([testUser.id, otherUser.id]).then(() => {
cy.visit(`/${testTeam.name}/channels/${testUser.id}__${otherUser.id}`);
cy.postMessage(':)');
});
// # Also open a GM with that user and a third user, post a message.
cy.apiCreateGroupChannel([sysadmin.id, otherUser.id, testUser.id]).then(({channel}) => {
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
cy.postMessage('hello');
});
const displayName = [sysadmin, otherUser].
map((member) => member.username).
sort((a, b) => a.localeCompare(b, 'en', {numeric: true})).
join(', ');
// # Observe DM and GM in LHS.
cy.uiGetLhsSection('DIRECT MESSAGES').findByText(displayName).should('be.visible');
cy.uiGetLhsSection('DIRECT MESSAGES').findByText(otherUser.username).should('be.visible');
// # System Console > Users Deactivate the user.
cy.apiLogout().apiAdminLogin();
activateUser(otherUser, false);
// # Go back to view team.
cy.apiLogin(testUser).visit(`/${testTeam.name}/channels/${testChannel.name}`).wait(TIMEOUTS.HALF_SEC);
// * On returning to the team the DM has been removed from LHS.
cy.uiGetLhsSection('DIRECT MESSAGES').findByText(otherUser.username).should('not.exist');
// * GM stays in LHS channel list.
cy.uiGetLhsSection('DIRECT MESSAGES').findByText(displayName).should('be.visible');
// # Open GM channel.
cy.uiGetLhsSection('DIRECT MESSAGES').findByText(displayName).click().wait(TIMEOUTS.HALF_SEC);
// * GM still has message box (is not archived)
cy.findByTestId('post_textbox').should('be.visible');
// # Restore the user.
cy.apiLogout().apiAdminLogin();
activateUser(otherUser, true);
});
function activateUser(user, activate) {
cy.visit('/admin_console/user_management/users');
// # Search for the user.
cy.get('#searchUsers').clear().type(user.email, {delay: TIMEOUTS.ONE_HUNDRED_MILLIS}).wait(TIMEOUTS.HALF_SEC);
cy.findByTestId('userListRow').within(() => {
if (activate) {
cy.findByText('Inactive').click().wait(TIMEOUTS.HALF_SEC);
// # Click on the "Activate" button.
cy.findByLabelText('User Actions Menu').findByText('Activate').click();
} else {
cy.findByText('Member').click().wait(TIMEOUTS.HALF_SEC);
// # Click on the "Deactivate" button.
cy.findByLabelText('User Actions Menu').findByText('Deactivate').click();
}
});
if (!activate) {
// # Verify the modal opened and then confirm.
cy.get('#confirmModal').should('exist').within(() => {
cy.get('#confirmModalButton').click().wait(TIMEOUTS.HALF_SEC);
});
}
}
});

Просмотреть файл

@@ -0,0 +1,302 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @system_console
import {
getEmailResetEmailTemplate,
getEmailVerifyEmailTemplate,
getRandomId,
verifyEmailBody,
} from '../../../utils';
const TIMEOUTS = require('../../../fixtures/timeouts');
describe('User Management', () => {
const newUsername = 'u' + getRandomId();
const newEmailAddr = newUsername + '@sample.mattermost.com';
let testTeam;
let testChannel;
let sysadmin;
let testUser;
before(() => {
cy.apiInitSetup().then(({team, channel, user}) => {
testChannel = channel;
testTeam = team;
testUser = user;
});
cy.apiAdminLogin().then((res) => {
sysadmin = res.user;
});
});
it('MM-T924 Users - Page through users list', () => {
cy.apiGetUsers().then(({users}) => {
const minimumNumberOfUsers = 60;
if (users.length < minimumNumberOfUsers) {
Cypress._.times(minimumNumberOfUsers - users.length, () => {
cy.apiCreateUser();
});
}
});
cy.visit('/admin_console/user_management/users');
cy.get('#searchableUserListTotal').then((el) => {
const count1 = el[0].innerText.replace(/\n/g, '').replace(/\s/g, ' ');
// * Can page through several pages of users.
cy.get('#searchableUserListNextBtn').should('be.visible').click();
// * Count at top changes appropriately.
cy.get('#searchableUserListTotal').then((el2) => {
const count2 = el2[0].innerText.replace(/\n/g, '').replace(/\s/g, ' ');
expect(count1).not.equal(count2);
});
// * Can page backward as well.
cy.get('#searchableUserListPrevBtn').should('be.visible').click();
});
});
it('MM-T928 Users - Change a user\'s email address', () => {
cy.visit('/admin_console/user_management/users');
// # Update config.
cy.apiUpdateConfig({
EmailSettings: {
RequireEmailVerification: true,
},
});
// * Blank email address: "Please enter a valid email address"
resetUserEmail(testUser.email, '', 'Please enter a valid email address');
// * Invalid email address: "Please enter a valid email address"
resetUserEmail(testUser.email, 'user-1(at)sample.mattermost.com', 'Please enter a valid email address');
// * Email address already in use: "An account with that email already exists."
resetUserEmail(testUser.email, 'sysadmin@sample.mattermost.com', 'An account with that email already exists.');
});
it('MM-T929 Users - Change a user\'s email address, with verification off', () => {
cy.visit('/admin_console/user_management/users');
// # Update config.
cy.apiUpdateConfig({
EmailSettings: {
RequireEmailVerification: false,
},
});
// # System admin changes new user's email address.
resetUserEmail(testUser.email, newEmailAddr, '');
// # Updates immediately in Profile for the user.
cy.get('#searchUsers').clear().type(newEmailAddr).wait(TIMEOUTS.HALF_SEC);
cy.get('.more-modal__details').should('be.visible').within(() => {
cy.findByText(newEmailAddr).should('exist');
});
// * User also receives email confirmation that email address has been changed.
checkResetEmail(testUser, newEmailAddr);
// # Logout, so that test user can login.
cy.apiLogout();
// * User cannot log in with old email address.
apiLogin(testUser.email, testUser.password).then((response) => {
expect(response.status).to.equal(401);
// # User logs in with username /password (no verification needed), then logs out again
cy.apiLogin({username: testUser.username, password: testUser.password}).apiLogout();
// # User logs in with new email address /password (no verification needed)
cy.apiLogin({username: newEmailAddr, password: testUser.password}).apiLogout();
});
// # Revert the changes.
cy.apiAdminLogin();
cy.visit('/admin_console/user_management/users');
resetUserEmail(newEmailAddr, testUser.email, '');
});
it('MM-T930 Users - Change a user\'s email address, with verification on', () => {
cy.visit('/admin_console/user_management/users');
// # Update Configs.
cy.apiUpdateConfig({
EmailSettings: {
RequireEmailVerification: true,
},
});
resetUserEmail(testUser.email, newEmailAddr, '');
cy.apiLogout();
// # Type email and password.
cy.get('#input_loginId').type(testUser.email);
cy.get('#input_password-input').type(testUser.password);
cy.get('#saveSetting').should('not.be.disabled').click();
// * Verify that logging in with the old e-mail works but requires e-mail verification.
cy.url().should('include', 'should_verify_email');
// # Log out.
cy.apiLogout();
// Verify e-mail.
verifyEmail({username: newUsername, email: newEmailAddr});
cy.wait(TIMEOUTS.HALF_SEC);
// * Verify that logging in with the old e-mail works.
cy.apiLogin({username: newEmailAddr, password: testUser.password}).apiLogout();
// # Revert the config.
cy.apiAdminLogin().apiUpdateConfig({
EmailSettings: {
RequireEmailVerification: false,
},
});
resetUserEmail(newEmailAddr, testUser.email, '');
});
it('MM-T931 Users - Can\'t update a user\'s email address if user has other signin method', () => {
// # Update config.
cy.apiUpdateConfig({
GitLabSettings: {
Enable: true,
},
});
cy.visit('/admin_console/user_management/users');
cy.apiCreateUser().then(({user: gitlabUser}) => {
cy.apiUpdateUserAuth(gitlabUser.id, gitlabUser.email, '', 'gitlab');
// # Search for the user.
cy.get('#searchUsers').clear().type(gitlabUser.email).wait(TIMEOUTS.HALF_SEC);
cy.findByTestId('userListRow').within(() => {
// # Open the actions menu.
cy.findByText('Member').click().wait(TIMEOUTS.HALF_SEC);
// # Click the Update email menu option.
cy.findByLabelText('User Actions Menu').findByText('Update Email').should('not.exist');
});
});
});
it('MM-T941 Users - Revoke all sessions for unreachable users', () => {
// # Login as a system user - User
cy.apiLogin(testUser);
// Visit the test channel
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
// # Revoke all sessions for the user
cy.externalRequest({user: sysadmin, method: 'post', path: `users/${testUser.id}/sessions/revoke/all`});
// # Visit default page and wait until it's redirected to login page
cy.visit('/');
cy.waitUntil(() => cy.url().then((url) => {
return url.includes('/login');
}), {timeout: TIMEOUTS.HALF_MIN});
// # Check if user's session is automatically logged out and the user is redirected to the login page
cy.url().should('contain', '/login');
});
function resetUserEmail(oldEmail, newEmail, errorMsg) {
cy.visit('/admin_console/user_management/users');
// # Search for the user.
cy.get('#searchUsers').clear().type(oldEmail).wait(TIMEOUTS.HALF_SEC);
cy.findByTestId('userListRow').within(() => {
// # Open the actions menu.
cy.findByText('Member').click().wait(TIMEOUTS.HALF_SEC);
// # Click the Update email menu option.
cy.findByLabelText('User Actions Menu').findByText('Update Email').click().wait(TIMEOUTS.HALF_SEC);
});
// # Verify the modal opened.
cy.findByTestId('resetEmailModal').should('exist');
// # Type the new e-mail address.
if (newEmail.length > 0) {
cy.get('input[type=email]').eq(0).clear().type(newEmail);
}
// # Click the "Reset" button.
cy.findByTestId('resetEmailButton').click();
// * Check for the error messages, if any.
if (errorMsg.length > 0) {
cy.get('form.form-horizontal').find('.has-error p.error').should('be.visible').and('contain', errorMsg);
// # Close the modal.
cy.findByLabelText('Close').click();
}
}
function checkResetEmail(user, newEmail) {
cy.getRecentEmail(user).then((data) => {
const {body: actualEmailBody, subject} = data;
// # Verify that the email subject is as expected.
expect(subject).to.contain('Your email address has changed');
// # Verify email body
const expectedEmailBody = getEmailResetEmailTemplate(newEmail);
verifyEmailBody(expectedEmailBody, actualEmailBody);
});
}
function verifyEmail(user) {
const baseUrl = Cypress.config('baseUrl');
// # Verify e-mail through verification link.
cy.getRecentEmail(user).then((data) => {
const {body: actualEmailBody, subject} = data;
// # Verify that the email subject is as expected.
expect(subject).to.contain('Email Verification');
// # Verify email body
const expectedEmailBody = getEmailVerifyEmailTemplate(user.email);
verifyEmailBody(expectedEmailBody, actualEmailBody);
// # Extract verification the link from the e-mail.
const line = actualEmailBody[4].split(' ');
const verificationLink = line[3].replace(baseUrl, '');
// # Complete verification.
cy.visit(verificationLink);
cy.findByText('Email Verified').should('be.visible');
cy.get('#input_loginId').should('be.visible').and('have.value', user.email);
});
}
function apiLogin(username, password) {
return cy.request({
headers: {'X-Requested-With': 'XMLHttpRequest'},
url: '/api/v4/users/login',
method: 'POST',
body: {login_id: username, password},
failOnStatusCode: false,
});
}
});

Просмотреть файл

@@ -0,0 +1,327 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Group: @channels @system_console
describe('Workspace deletion', () => {
const host = window.location.host;
beforeEach(() => {
cy.apiLogout();
cy.apiAdminLogin();
});
it('Workspace deletion cta is visible for free trials', () => {
// Professional Yearly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_3',
is_free_trial: 'true',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete your workspace').should('exist');
cy.findByText(`${host}`).should('exist');
});
it('Workspace deletion cta is not visible for cloud professional with a yearly plan', () => {
// Professional Yearly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_4',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
// Text is separated by an html <a> tag, just get the last half.
cy.findByText('Delete your workspace').should('not.exist');
cy.findByText(`${host}`).should('not.exist');
cy.findByText('Cancel your subscription').should('exist');
cy.findByText('At this time, deleting a workspace can only be done with the help of a customer support representative.').should('exist');
});
it('Workspace deletion cta is not visible for cloud enterprise with a yearly plan', () => {
// Enterprise Yearly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_5',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
// Text is separated by an html <a> tag, just get the last half.
cy.findByText('Delete your workspace').should('not.exist');
cy.findByText(`${host}`).should('not.exist');
cy.findByText('Cancel your subscription').should('exist');
cy.findByText('At this time, deleting a workspace can only be done with the help of a customer support representative.').should('exist');
});
it('Workspace deletion cta is visible for cloud free', () => {
// Free.
const subscription = {
id: 'sub_test1',
product_id: 'prod_1',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete your workspace').should('exist');
cy.findByText(`${host}`).should('exist');
});
it('Workspace deletion cta is visible for cloud professional with a monthly plan', () => {
// Professional Monthly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_2',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete your workspace').should('exist');
cy.findByText(`${host}`).should('exist');
});
it('Workspace deletion cta is not visible for cloud enterprise with a monthly plan', () => {
// Professional Yearly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_3',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
// Text is separated by an html <a> tag, just get the last half.
cy.findByText('Delete your workspace').should('not.exist');
cy.findByText(`${host}`).should('not.exist');
cy.findByText('Cancel your subscription').should('exist');
cy.findByText('At this time, deleting a workspace can only be done with the help of a customer support representative.').should('exist');
});
it('Workspace deletion modal > downgrade button is not visible for cloud free', () => {
// Free.
const subscription = {
id: 'sub_test1',
product_id: 'prod_1',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete Workspace').click();
cy.findByText('Are you sure you want to delete?').should('exist');
cy.findByText('Downgrade To Free').should('not.exist');
});
it('Workspace deletion modal > downgrade button is visible for cloud professional', () => {
// Professional Monthly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_2',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete Workspace').click();
cy.findByText('Are you sure you want to delete?').should('exist');
cy.findByText('Downgrade To Free').should('exist');
});
it('Workspace deletion modal > downgrade button is not visible for free trials', () => {
// Free.
const subscription = {
id: 'sub_test1',
product_id: 'prod_3',
is_free_trial: 'true',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete Workspace').click();
cy.findByText('Are you sure you want to delete?').should('exist');
cy.findByText('Downgrade To Free').should('not.exist');
});
it('Workspace deletion modal > delete workspace button click > feedback modal shown before submitting deletion request', () => {
// Professional Monthly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_2',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete Workspace').click();
cy.findByText('Are you sure you want to delete?').should('exist');
cy.get('.DeleteWorkspaceModal__Buttons-Delete').contains('Delete Workspace').should('exist').click();
cy.findByText('Please share your reason for deleting').should('exist');
});
it('Workspace deletion modal > delete workspace button click > feedback modal requires option selected to enable submit', () => {
// Professional Monthly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_2',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete Workspace').click();
cy.findByText('Are you sure you want to delete?').should('exist');
cy.get('.DeleteWorkspaceModal__Buttons-Delete').contains('Delete Workspace').should('exist').click();
cy.findByText('Please share your reason for deleting').should('exist');
cy.findByText('No longer found value').click();
cy.get('.GenericModal__button.confirm').contains('Delete Workspace').should('be.enabled');
});
it('Workspace deletion modal > downgrade workspace button click > feedback modal shown before submitting downgrade request', () => {
// Professional Monthly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_2',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete Workspace').click();
cy.findByText('Are you sure you want to delete?').should('exist');
cy.findByText('Downgrade To Free').should('exist').click();
cy.findByText('Please share your reason for downgrading').should('exist');
});
it('Workspace deletion modal > downgrade workspace button click > feedback modal requires option selected to enable submit', () => {
// Professional Monthly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_2',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete Workspace').click();
cy.findByText('Are you sure you want to delete?').should('exist');
cy.findByText('Downgrade To Free').should('exist').click();
cy.findByText('Please share your reason for downgrading').should('exist');
cy.findByText('Experienced technical issues').click();
cy.findByText('Downgrade').should('be.enabled');
});
it('Workspace deletion modal > delete workspace > after survey, a success modal is displayed when the deletion succeeds', () => {
cy.intercept('DELETE', '/api/v4/cloud/delete-workspace', {statusCode: 200, body: {message: 'Status OK'}}).as('deleteWorkspace');
// Professional Monthly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_2',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete Workspace').click();
cy.findByText('Are you sure you want to delete?').should('exist');
cy.get('.DeleteWorkspaceModal__Buttons-Delete').contains('Delete Workspace').should('exist').click();
cy.findByText('Please share your reason for deleting').should('exist');
cy.findByText('No longer found value').click();
cy.get('.GenericModal__button.confirm').contains('Delete Workspace').should('be.enabled').click();
cy.wait('@deleteWorkspace');
cy.get('.result_modal').should('exist');
cy.findByText('Your workspace has been deleted').should('exist');
});
it('Workspace deletion modal > delete workspace > after survey, a failure modal is displayed when the deletion fails', () => {
cy.intercept('DELETE', '/api/v4/cloud/delete-workspace', {statusCode: 500}).as('deleteWorkspace');
// Professional Monthly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_2',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete Workspace').click();
cy.findByText('Are you sure you want to delete?').should('exist');
cy.get('.DeleteWorkspaceModal__Buttons-Delete').contains('Delete Workspace').should('exist').click();
cy.findByText('Please share your reason for deleting').should('exist');
cy.findByText('No longer found value').click();
cy.get('.GenericModal__button.confirm').contains('Delete Workspace').should('be.enabled').click();
cy.wait('@deleteWorkspace');
cy.get('.result_modal').should('exist');
cy.findByText('Workspace deletion failed').should('exist');
});
it('Workspace deletion modal > downgrade workspace > after survey, a success modal is displayed when the downgrade succeeds', () => {
cy.intercept('PUT', '/api/v4/cloud/subscription', {statusCode: 200, body: {message: 'Status OK'}}).as('downgradeWorkspace');
// Professional Monthly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_2',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete Workspace').click();
cy.findByText('Are you sure you want to delete?').should('exist');
cy.findByText('Downgrade To Free').should('exist').click();
cy.findByText('Please share your reason for downgrading').should('exist');
cy.findByText('Experienced technical issues').click();
cy.findByText('Downgrade').should('be.enabled').click();
cy.wait('@downgradeWorkspace');
cy.get('.cloud_subscribe_result_modal').should('exist');
cy.findByText('You are now subscribed to Cloud Free').should('exist');
});
it('Workspace deletion modal > downgrade workspace > after survey, a failure modal is displayed when the downgrade fails', () => {
cy.intercept('PUT', '/api/v4/cloud/subscription', {statusCode: 500}).as('downgradeWorkspace');
// Professional Monthly.
const subscription = {
id: 'sub_test1',
product_id: 'prod_2',
is_free_trial: 'false',
};
cy.simulateSubscription(subscription);
cy.visit('/admin_console/billing/subscription');
cy.findByText('Delete Workspace').click();
cy.findByText('Are you sure you want to delete?').should('exist');
cy.findByText('Downgrade To Free').should('exist').click();
cy.findByText('Please share your reason for downgrading').should('exist');
cy.findByText('Experienced technical issues').click();
cy.findByText('Downgrade').should('be.enabled').click();
cy.wait('@downgradeWorkspace');
cy.get('.cloud_subscribe_result_modal').should('exist');
cy.findByText('We were unable to change your plan').should('exist');
});
});