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

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

@@ -0,0 +1,113 @@
// 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 @account_settings
describe('Account Settings', () => {
let testUser: Cypress.UserProfile;
let testTeam: Cypress.Team;
let offTopic: string;
before(() => {
// # Login as new user and visit off-topic
cy.apiInitSetup({userPrefix: 'other', loginAfter: true}).then(({offTopicUrl, user, team}) => {
cy.visit(offTopicUrl);
offTopic = offTopicUrl;
testUser = user;
testTeam = team;
});
});
it('MM-T2049 Account Settings link in own popover', () => {
// # Click avatar to open profile popover
cy.get('div.status-wrapper').should('be.visible').click();
// # Click account settings link
cy.get('#accountSettings').should('be.visible').click();
// # Check if account settings modal is open
cy.get('#accountSettingsModal').should('be.visible');
cy.uiClose();
});
it('MM-T2081 Password: Error on blank', () => {
// # Go to Profile > Security
cy.uiOpenProfileModal('Security');
// * Check that the Security tab is loaded
cy.get('#securityButton').should('be.visible');
// # Click the Security tab
cy.get('#securityButton').click();
// # Click "Edit" to the right of "Password"
cy.get('#passwordEdit').should('be.visible').click();
// # Save the settings
cy.uiSave();
// * Check that there is an error
cy.get('#clientError').should('be.visible').should('contain', 'Please enter your current password.');
cy.get('#serverError').should('not.exist');
cy.uiClose();
});
it('MM-T2074 New email not visible to other users until it has been confirmed', () => {
// # Login as admin
cy.apiLogout();
cy.apiAdminLogin();
// * Set require email verification to true
cy.visit('/admin_console/authentication/email');
cy.get('[id="EmailSettings.EnableSignInWithEmailtrue"]').should('be.visible').click();
cy.get('#saveSetting').invoke('attr', 'disabled').
then((disabled) => {
disabled ? '' : cy.uiSave();
});
cy.visit(offTopic);
// # Create user
cy.apiCreateUser({prefix: 'test'}).then(({user: newUser}) => {
// # Add user to team
cy.apiAddUserToTeam(testTeam.id, newUser.id).then(() => {
// # Create DM channel
cy.apiCreateDirectChannel([testUser.id, newUser.id]).then(({channel}) => {
// # Login to first user
cy.uiLogout();
cy.uiLogin(testUser);
cy.visit(offTopic);
// * Update email
const oldEMail = testUser.email;
const newEMail = 'test@example.com';
cy.uiOpenProfileModal();
cy.get('#emailEdit').should('be.visible').click();
cy.get('#primaryEmail').should('be.visible').type(newEMail);
cy.get('#confirmEmail').should('be.visible').type(newEMail);
cy.get('#currentPassword').should('be.visible').type(testUser.password);
cy.uiSaveAndClose();
// * Send DM
cy.postMessageAs({sender: testUser, message: `@${newUser.username}`, channelId: channel.id});
// # Login to 2nd user
cy.uiLogout();
cy.uiLogin(newUser);
// * Check if email updated
cy.visit(`/${testTeam.name}/messages/@${testUser.username}`);
cy.get('#channelIntro .user-popover').should('be.visible').click();
cy.get('#user-profile-popover').should('be.visible').should('contain', oldEMail);
});
});
});
});
});

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

@@ -0,0 +1,49 @@
// 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 @account_setting
import * as TIMEOUTS from '../../../fixtures/timeouts';
describe('Profile > Profile Settings', () => {
let otherUser: Cypress.UserProfile;
let testChannel: Cypress.Channel;
before(() => {
cy.apiInitSetup().then(({team, channel, offTopicUrl}) => {
testChannel = channel;
cy.apiCreateUser().then(({user}) => {
otherUser = user;
cy.apiAddUserToTeam(team.id, user.id).then(() => {
cy.apiAddUserToChannel(testChannel.id, user.id);
});
});
// # Go to off-topic
cy.visit(offTopicUrl);
});
});
it('MM-T285 Status Menu stays open', () => {
// # Click the hamburger button
cy.uiGetSetStatusButton().click();
// * Menu should be visible
cy.uiGetStatusMenu();
// # Post a message as other user
cy.postMessageAs({sender: otherUser, message: 'abc', channelId: testChannel.id}).wait(TIMEOUTS.FIVE_SEC);
// * Menu should still be visible
cy.uiGetStatusMenu();
});
});

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

@@ -0,0 +1,78 @@
// 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 @account_setting
describe('Profile > Profile Settings > Position', () => {
beforeEach(() => {
cy.apiAdminLogin();
cy.apiInitSetup({loginAfter: true}).then(({offTopicUrl}) => {
// # Visit off-topic channel
cy.visit(offTopicUrl);
});
});
it('MM-T2063 Position', () => {
const position = 'Master hacker';
// # Open 'Profile' modal and view the default 'Profile Settings'
cy.uiOpenProfileModal().within(() => {
// # Open 'Position' setting
cy.findByRole('heading', {name: 'Position'}).should('be.visible').click();
// # Enter new 'Position'
cy.findByRole('textbox', {name: 'Position'}).should('be.visible').type(position);
// # Save and close the modal
cy.uiSaveAndClose();
});
// # Post message in the main channel
cy.postMessage('hello from master hacker');
// # Click on the profile image
cy.get('.profile-icon > img').as('profileIconForPopover').click();
// # Verify that the popover is visible and contains position
cy.contains('#user-profile-popover', position).should('be.visible');
});
it('MM-T2064 Position / 128 characters', () => {
const longPosition = 'Master Hacker II'.repeat(8);
// # Open 'Profile' modal and view the default 'Profile Settings'
cy.uiOpenProfileModal().within(() => {
const minPositionHeader = () => cy.findByRole('heading', {name: 'Position'});
const maxPositionInput = () => cy.findByRole('textbox', {name: 'Position'});
// # Fill-in the position field with a value of 128 characters
minPositionHeader().click();
maxPositionInput().type(longPosition);
cy.uiSave();
maxPositionInput().should('not.exist');
minPositionHeader().click();
maxPositionInput().invoke('val').then((val) => {
// * Verify that the input value is 128 characters
expect(val.toString().length).to.equal(128);
});
// # Try to edit the field with maximum characters
maxPositionInput().focus().type('random');
maxPositionInput().invoke('val').then((val) => {
// * Verify that the position hasn't changed
expect(val).to.equal(longPosition);
});
// # Save position
cy.uiSave();
});
});
});

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

@@ -0,0 +1,233 @@
// 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 @account_setting
import * as TIMEOUTS from '../../../../fixtures/timeouts';
import {reUrl, getRandomId} from '../../../../utils';
describe('Profile > Profile Settings > Email', () => {
let siteName;
let testUser: Cypress.UserProfile;
let otherUser;
let offTopicUrl;
let origConfig: Cypress.AdminConfig;
before(() => {
// Get config
cy.apiGetConfig().then(({config}) => {
origConfig = config;
const newConfig = {
...origConfig,
EmailSettings: {
...origConfig.EmailSettings,
RequireEmailVerification: true,
},
};
cy.apiUpdateConfig(newConfig).then(({config}) => {
siteName = config.TeamSettings.SiteName;
});
cy.apiInitSetup().then(({user, offTopicUrl: url}) => {
testUser = user;
offTopicUrl = url;
cy.apiVerifyUserEmailById(testUser.id);
return cy.apiCreateUser({});
}).then(({user: user1}) => {
otherUser = user1;
cy.apiLogin(testUser);
cy.visit(offTopicUrl);
});
});
});
beforeEach(() => {
// # Go to Profile
cy.uiOpenProfileModal();
});
afterEach(() => {
// # Close modal
cy.get('body').type('{esc}');
});
it('MM-T2065 Email: Can "change" to existing email address and save', () => {
// # Click "Edit" to the right of "Email"
cy.get('#emailEdit').should('be.visible').click();
// # Type the same email
cy.get('#primaryEmail').should('be.visible').type(testUser.email);
cy.get('#confirmEmail').should('be.visible').type(testUser.email);
cy.get('#currentPassword').should('be.visible').type('SampleUs@r-1');
// # Save the settings
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
// * Check that the email verification message is not showed.
cy.get('.announcement-bar').should('not.exist');
});
it('MM-T2066 email address required', () => {
// # Click "Edit" to the right of "Email"
cy.get('#emailEdit').should('be.visible').click();
// # Save the settings
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
// * Check that the correct error message is shown.
cy.get('#clientError').should('be.visible').should('have.text', 'Please enter a valid email address');
});
it('MM-T2067 email address already taken error', () => {
// # Click "Edit" to the right of "Email"
cy.get('#emailEdit').should('be.visible').click();
// # Type different email
cy.get('#primaryEmail').should('be.visible').type(otherUser.email);
cy.get('#confirmEmail').should('be.visible').type(otherUser.email);
cy.get('#currentPassword').should('be.visible').type(otherUser.password);
// # Save the settings
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
// * Check that the correct error message is shown.
cy.get('#serverError').should('be.visible').should('have.text', 'An account with that email already exists.');
});
it('MM-T2068 email address and confirmation don\'t match', () => {
// # Click "Edit" to the right of "Email"
cy.get('#emailEdit').should('be.visible').click();
// # Type some random email
cy.get('#primaryEmail').should('be.visible').type('random@example.com');
cy.get('#confirmEmail').should('be.visible').clear();
cy.get('#currentPassword').should('be.visible').type('randompass');
// # Save the settings
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
// * Check that the correct error message is shown.
cy.get('#clientError').should('be.visible').should('have.text', 'The new emails you entered do not match.');
});
// This test is a combination of 4 sub-tests because they are sub-parts of the same test.
// Doing them individually would have a dependency with the previous test.
// Hence, a combined single test for everything is better.
it('MM-T2069 Email: Can update email address and verify through email notification', () => {
// # Click "Edit" to the right of "Email"
cy.get('#emailEdit').should('be.visible').click();
const randomId = getRandomId();
const username = `user-${randomId}`;
const email = `${username}@example.com`;
// # Type new email
cy.get('#primaryEmail').should('be.visible').type(email);
cy.get('#confirmEmail').should('be.visible').type(email);
cy.get('#currentPassword').should('be.visible').type(testUser.password);
// # Save the settings and close
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
cy.uiClose();
// * Verify the announcement bar
cy.get('.announcement-bar').should('be.visible').should('contain.text', 'Check your email inbox to verify the address.');
// # Reload the page
cy.reload();
// * Check that the email verification message is not showed.
cy.get('.announcement-bar').should('not.exist');
cy.getRecentEmail({username, email}).then((data) => {
// * Verify the subject
expect(data.subject).to.equal(`[${siteName}] Verify new email address`);
// * Verify the body
expect(data.body).to.contain('You successfully updated your email');
const matched = data.body[6].match(reUrl);
assert(matched.length > 0);
const permalink = matched[0];
// # Click on the link
cy.visit(permalink);
// * Verify announcement bar
cy.get('.announcement-bar').should('be.visible').should('contain.text', 'Email verified');
// # Wait for one second for the mail to be sent out.
cy.wait(TIMEOUTS.FIVE_SEC);
cy.getRecentEmail(testUser).then(({subject}) => {
// * Verify the subject
expect(subject).to.equal(`[${siteName}] Your email address has changed`);
});
cy.uiOpenProfileModal();
// * Verify new email address
cy.get('#emailDesc').should('be.visible').should('have.text', email);
});
});
it('MM-T2073 - Verify email verification message after logout', () => {
// # Click "Edit" to the right of "Email"
cy.get('#emailEdit').should('be.visible').click();
const randomId = getRandomId();
const username = `user-${randomId}`;
const email = `${username}@example.com`;
// # Type new email
cy.get('#primaryEmail').should('be.visible').type(email);
cy.get('#confirmEmail').should('be.visible').type(email);
cy.get('#currentPassword').should('be.visible').type(testUser.password);
// # Save the settings
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
// # Close modal then logout
cy.get('body').type('{esc}');
cy.uiOpenUserMenu('Log Out');
// # Wait for one second for the mail to be sent out.
cy.wait(TIMEOUTS.ONE_SEC);
cy.getRecentEmail({username, email}).then((data) => {
// * Verify the subject
expect(data.subject).to.equal(`[${siteName}] Verify new email address`);
// * Verify email body
expect(data.body[1]).to.contain('You successfully updated your email');
const matched = data.body[6].match(reUrl);
assert(matched.length > 0);
const permalink = matched[0];
cy.visit(permalink);
// * Verify login text
cy.get('.AlertBanner.success').should('be.visible').within(() => {
cy.get('.AlertBanner__title').should('contain.text', 'Email Verified');
});
// # Do login
cy.get('#input_loginId').should('be.visible').clear().type(email);
cy.get('#input_password-input').should('be.visible').type(testUser.password);
cy.get('#saveSetting').should('not.be.disabled').click();
// * Check that the email verification message is not showed.
cy.get('.announcement-bar').should('not.exist');
});
});
});

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

@@ -0,0 +1,84 @@
// 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 @account_setting
describe('Profile > Profile Settings > Full Name', () => {
let testUser;
before(() => {
// # Login as new user and visit off-topic
cy.apiInitSetup({loginAfter: true}).then(({user, offTopicUrl}) => {
testUser = user;
cy.visit(offTopicUrl);
});
});
it('MM-T2043 Enter first name', () => {
// # Go to Profile
cy.uiOpenProfileModal();
// # Click "Edit" to the right of "Full Name"
cy.get('#nameEdit').should('be.visible').click();
// # Clear the first name
cy.get('#firstName').clear();
// # Type a new first name
cy.get('#firstName').should('be.visible').type(testUser.first_name + '_new');
// # Save the settings
cy.uiSave();
// * Check that the first name was correctly updated
cy.get('#nameDesc').should('be.visible').should('contain', testUser.first_name + '_new ' + testUser.last_name);
// # Close the modal
cy.uiClose();
});
it('MM-T2042 Full Name starting blank stays blank', () => {
// # Go to Profile
cy.uiOpenProfileModal();
// # Click "Edit" to the right of "Full Name"
cy.get('#nameEdit').should('be.visible').click();
// # Clear the first name
cy.get('#firstName').should('be.visible').clear();
// # Clear the last name
cy.get('#lastName').should('be.visible').clear();
// # Save the settings
cy.uiSave();
// # Click "Edit" to the right of "Full Name"
cy.get('#nameEdit').should('be.visible').click();
// # Save the settings
cy.uiSave();
// * Check that the full name was correctly cleared
cy.findByText("Click 'Edit' to add your full name").should('be.visible');
// # Click "Edit" to the right of "Full Name"
cy.get('#nameEdit').should('be.visible').click();
// * Check that first name is blank
cy.get('#firstName').should('be.visible').should('have.value', '');
// * Check that last name is blank
cy.get('#lastName').should('be.visible').should('have.value', '');
// # Close the modal
cy.uiClose();
});
});

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

@@ -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 @account_setting
import {getRandomId} from '../../../../utils';
describe('Profile > Profile Settings> Full Name', () => {
let firstUser;
let secondUser;
const firstName = 'This Is a Long Name';
const lastName = 'That Should Truncate';
before(() => {
cy.apiInitSetup().then(({team, user, offTopicUrl}) => {
firstUser = user;
cy.apiCreateUser().then(({user: user1}) => {
secondUser = user1;
cy.apiAddUserToTeam(team.id, secondUser.id);
cy.apiLogin(firstUser);
cy.visit(offTopicUrl);
});
});
});
it('MM-T2046 Full Name - Truncated in popover', () => {
// # Go to Profile -> Profile Settings -> Full Name -> Edit
cy.uiOpenProfileModal();
// # Open Full Name section
cy.get('#nameDesc').click();
// # Enter First Name `This Is a Very Long Name`
cy.get('#firstName').clear().type(firstName);
// # Enter Last Name `That Should Truncate`
cy.get('#lastName').clear().type(lastName);
// # Save
cy.get('#saveSetting').click();
// * Full name field shows first and last name.
cy.contains('#nameDesc', `${firstName} ${lastName}`);
// # Close account settings modal
cy.uiClose();
});
it('MM-T2047 Truncated in popover (visual verification)', () => {
// # Open user profile popover
cy.postMessage(`this is a test message ${getRandomId()}`);
cy.getLastPostId().then((postId) => {
cy.get(`#post_${postId}`).should('be.visible');
cy.get(`#post_${postId} img`).click();
cy.get('#user-profile-popover').should('be.visible');
// * Popover user name should show truncated to 'This Is a Long Name That Should Tr...'
cy.findByTestId(`popover-fullname-${firstUser.username}`).should('have.css', 'text-overflow', 'ellipsis');
});
});
it('MM-T2048 Empty full name: @ still displays before username', () => {
// # Open any user list ("View Members", "Add Members", "Manage Members", ..)
cy.uiOpenTeamMenu('View Members');
// # Find a user who hasn't set their full name
cy.get('.modal-title').should('be.visible');
cy.get('#searchUsersInput').should('be.visible').type(secondUser.nickname);
// * Username is preceded with `@`, consistent with other users
cy.contains('button.user-popover', `@${secondUser.username}`);
});
});

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

@@ -0,0 +1,42 @@
// 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 @account_setting
describe('Account Settings', () => {
before(() => {
// # Login as new user and visit off-topic
cy.apiInitSetup({loginAfter: true}).then(({offTopicUrl}) => {
cy.visit(offTopicUrl);
});
});
it('MM-T2045 Full Name - Link in help text', () => {
// # Go to Profile
cy.uiOpenProfileModal();
// * Ensure that the Profile tab is loaded
cy.get('#generalSettingsTitle').should('be.visible').should('contain', 'Profile');
// # Click "Edit" to the right of Full Name
cy.get('#nameEdit').click();
// # Click "Notifications" link in help text
cy.get('#extraInfo').within(() => {
cy.findByText('Notifications').click();
});
// * Verify that the modal switched to "Profile" modal
cy.findByRole('dialog', {name: 'Profile'}).should('be.visible');
// * Verify that the view switches to notifications tab
cy.get('#notificationSettingsTitle').should('be.visible').should('contain', 'Notifications');
});
});

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

@@ -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 @account_setting
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('Settings > Sidebar > General', () => {
let testUser;
let testTeam;
before(() => {
// # Login as new user and visit off-topic
cy.apiInitSetup({loginAfter: true}).then(({team, user, offTopicUrl}) => {
testUser = user;
testTeam = team;
cy.visit(offTopicUrl);
});
});
it('MM-T3848 No nickname is present', () => {
// # Open 'Profile' modal and view the default 'Profile'
cy.uiOpenProfileModal().within(() => {
// # Open 'Nickname' setting
cy.uiGetHeading('Nickname').click();
// # Clear the nickname text field contents
cy.uiGetTextbox('Nickname').should('be.visible').clear();
// # Save and close the modal
cy.uiSaveAndClose();
});
// # Open team menu and click "View Members"
cy.uiOpenTeamMenu('View Members');
// # Search for username and check that no nickname is present
cy.get('.modal-title').should('be.visible');
cy.get('#searchUsersInput').should('be.visible').type(testUser.first_name).wait(TIMEOUTS.ONE_SEC);
cy.findByTestId('userListItemDetails').find('.more-modal__name').should('be.visible').then((el) => {
expect(getInnerText(el)).equal(`@${testUser.username} - ${testUser.first_name} ${testUser.last_name}`);
});
// # Close Team Members modal
cy.uiClose();
});
it('MM-T268 Profile > Profile Settings > Add Nickname', () => {
const newNickname = 'victor_nick';
// # Open 'Profile' modal and view the default 'Profile Settings'
cy.uiOpenProfileModal().within(() => {
// # Open 'Nickname' setting
cy.uiGetHeading('Nickname').click();
// # Clear the nickname text field contents
cy.uiGetTextbox('Nickname').should('be.visible').clear().type('victor_nick');
// # Save and close the modal
cy.uiSaveAndClose();
});
// # Open team menu and click "View Members"
cy.uiOpenTeamMenu('View Members');
// # Search for username and check that expected nickname is present
cy.get('.modal-title').should('be.visible');
cy.get('#searchUsersInput').should('be.visible').type(testUser.first_name).wait(TIMEOUTS.ONE_SEC);
cy.findByTestId('userListItemDetails').find('.more-modal__name').should('be.visible').then((el) => {
expect(getInnerText(el)).equal(`@${testUser.username} - ${testUser.first_name} ${testUser.last_name} (${newNickname})`);
});
// # Close Channel Members modal
cy.uiClose();
});
it('MM-T2060 Nickname and username styles', () => {
cy.apiCreateChannel(testTeam.id, 'channel-test', 'Channel').then(({channel}) => {
// # Go to test channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # 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();
cy.uiClose();
// # Open channel menu and click 'Add Members'
cy.uiOpenChannelMenu('Add Members');
// * Verify that the modal is open
cy.get('#addUsersToChannelModal').should('be.visible').findByText(`Add people to ${channel.display_name}`);
// # Type into the input box to search for a user
cy.get('#selectItems input').typeWithForce('sys').wait(TIMEOUTS.ONE_SEC);
// * Verify that the username span contains the '@' symbol and the dark colour
cy.get('#multiSelectList > div > .more-modal__details > .more-modal__name > span').should('contain', '@').and('have.css', 'color', 'rgb(63, 67, 80)');
// # Close modal
cy.get('body').type('{esc}');
// # Open DM modal from the sidebar
cy.uiAddDirectMessage().click();
// # Go to direct messages modal
cy.get('.more-modal').should('be.visible').within(() => {
cy.findByText('Direct Messages').click();
cy.get('#selectItems input').typeWithForce('@');
// * Verify that the username span contains the '@' symbol and the dark colour
cy.get('.more-modal__details > .more-modal__name').should('contain', '@').and('have.css', 'color', 'rgb(63, 67, 80)');
});
// # Exit the modal
cy.get('body').type('{esc}');
});
});
it('MM-T2061 Nickname should reset on cancel of edit', () => {
// # Open 'Profile' modal and view the default 'Profile Settings'
cy.uiOpenProfileModal().within(() => {
// # Open 'Nickname' setting
cy.uiGetHeading('Nickname').click();
// # Clear the nickname text field contents
cy.uiGetTextbox('Nickname').should('be.visible').clear().type('nickname_edit');
// # Cancel the edit of nickname
cy.uiCancelButton().click();
});
// # Click edit of nickname
cy.uiGetHeading('Nickname').click();
// * Check if element is present and contains old nickname
cy.uiGetTextbox('Nickname').should('be.visible').should('contain', '');
// # Close the modal
cy.uiClose();
});
it('MM-T2062 Clear nickname and save', () => {
// # Open 'Profile' modal and view the default 'Profile Settings'
cy.uiOpenProfileModal().within(() => {
// # Open 'Nickname' setting
cy.uiGetHeading('Nickname').click();
// # Clear the nickname
cy.uiGetTextbox('Nickname').clear();
// * Check if nickname element is present and it does not contain any nickname
cy.uiGetTextbox('Nickname').should('contain', '');
cy.uiSaveButton().click();
});
// * Verify nickname help text is visible
cy.get('#nicknameDesc').should('be.visible').should('contain', "Click 'Edit' to add a nickname");
// # Close the modal
cy.uiClose();
});
function getInnerText(el) {
return el[0].innerText.replace(/\n/g, '').replace(/\s/g, ' ');
}
});

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

@@ -0,0 +1,88 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// Stage: @prod
// Group: @channels @account_setting
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('Account Settings', () => {
beforeEach(() => {
cy.apiAdminLogin().apiInitSetup({loginAfter: true}).its('user').as('user');
});
it('MM-T2079 Can remove profile pic then choose different pic without saving in between', function() {
// # Add a profile picture (aka "old profile picture")
setInitialPicture(this.user);
cy.visit('/');
// # Save the id of the old picture
getProfilePictureId().as('idOld');
// # Open Profile > Profile Settings > Profile Picture > Edit
cy.uiOpenProfileModal().findByRole('button', {name: /picture edit/i}).click();
// # Click the X to remove the old profile picture but do not click save
cy.findByRole('button', {name: /remove profile picture/i}).click();
// # Select a new profile picture and click Save
cy.findByTestId('uploadPicture').attachFile('png-image-file.png');
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
cy.findByRole('button', {name: /close/i}).click();
// * Verify that new profile image exists and isn't equal to the old one
getProfilePictureId().then((idNew) => expect(idNew).to.exist.and.not.to.be.equal(this.idOld));
});
it('MM-T2075_1 Profile Picture: Cancel out of adding profile picture', () => {
verifyProfilePictureDoesNotUpdateAfterCancel();
});
it('MM-T2075_2 Profile Picture: Cancel out of changing profile picture ', function() {
// # Add a profile picture (aka "old profile picture")
setInitialPicture(this.user);
verifyProfilePictureDoesNotUpdateAfterCancel();
});
});
function getProfilePictureId() {
return cy.uiGetProfileHeader().find('.Avatar').invoke('attr', 'src').then((urlString) => {
const url = new URL(urlString);
const params = new URLSearchParams(url.search);
return params.get('_');
});
}
function setInitialPicture(user) {
cy.apiUploadFile('image', 'mattermost-icon.png', {
url: `/api/v4/users/${user.id}/image`,
method: 'POST',
successStatus: 200,
});
}
function verifyProfilePictureDoesNotUpdateAfterCancel() {
let idOld;
cy.visit('/');
// # Save the id of the old picture
getProfilePictureId().then((id) => {
idOld = id;
});
// # Open Profile > Profile Settings > Profile Picture > Edit
cy.uiOpenProfileModal().findByRole('button', {name: /picture edit/i}).click();
// # Select a new profile picture
cy.findByTestId('uploadPicture').attachFile('png-image-file.png');
cy.uiCancel().wait(TIMEOUTS.HALF_SEC);
cy.uiClose();
// * Verify that 'new' profile image exists and equal to the old one
getProfilePictureId().then((idNew) => expect(idNew).to.equal(idOld));
}

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

@@ -0,0 +1,92 @@
// 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 @account_setting
// TODO: Remove import once e2e/cypress/tests/support/index.ts is converted to Typescript.
import 'cypress-file-upload';
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('Profile > Profile Settings > Profile Picture', () => {
before(() => {
cy.apiInitSetup({loginAfter: true}).then(({offTopicUrl}) => {
cy.visit(offTopicUrl);
});
});
it('MM-T2080 Can remove profile pic', () => {
const customImageMatch = 'image?_=';
// * Verify the default profile image is shown first
cy.uiGetProfileHeader().
find('.Avatar').
should('have.attr', 'src').
and('not.include', customImageMatch);
// # Go to Profile
cy.uiOpenProfileModal();
// # Click "Edit" to the right of "Profile Picture"
cy.get('#pictureEdit').should('be.visible').click();
// # Upload and save profile picture
cy.findByTestId('uploadPicture').attachFile('mattermost-icon.png');
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
// # Close modal
cy.get('body').type('{esc}');
// * Profile picture is updated
cy.uiGetProfileHeader().
find('.Avatar').
should('have.attr', 'src').
and('include', customImageMatch);
// # Go to Profile
cy.uiOpenProfileModal();
// # Click "Edit" to the right of "Profile Picture"
cy.get('#pictureEdit').should('be.visible').click();
// # Remove profile picture
cy.findByTestId('removeSettingPicture').click();
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
// * Check that we are back in the "General" section of the Profile
cy.get('#pictureEdit').should('be.visible');
// # Close modal
cy.get('body').type('{esc}');
// * Verify the default profile image is shown
cy.uiGetProfileHeader().
find('.Avatar').
should('have.attr', 'src').
and('not.include', customImageMatch);
});
it('MM-T2077 Profile picture: non image file shows error', () => {
// # Go to Profile
cy.uiOpenProfileModal();
// # Click "Edit" to the right of "Profile Picture"
cy.get('#pictureEdit').should('be.visible').click();
// # Upload and save profile picture
cy.findByTestId('uploadPicture').attachFile('txt-changed-as-png.png');
cy.uiSave().wait(TIMEOUTS.HALF_SEC);
// # Verify error message
cy.get('.has-error').
should('be.visible').
and('contain', 'Image limits check failed. Resolution is too high.');
});
});

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

@@ -0,0 +1,246 @@
// 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 @account_setting
import {getRandomId} from '../../../../utils';
describe('Settings > Sidebar > General > Edit', () => {
let testTeam;
let testUser;
let testChannel;
let otherUser;
let offTopicUrl;
before(() => {
// # Login as admin and visit off-topic
cy.apiInitSetup().then(({user, team, channel, offTopicUrl: url}) => {
testUser = user;
testTeam = team;
testChannel = channel;
offTopicUrl = url;
cy.apiCreateUser({prefix: 'other'}).then(({user: user1}) => {
otherUser = user1;
cy.apiAddUserToTeam(testTeam.id, otherUser.id).then(() => {
cy.apiAddUserToChannel(testChannel.id, otherUser.id);
});
});
cy.visit(offTopicUrl);
});
});
beforeEach(() => {
// # Go to Profile
cy.uiOpenProfileModal();
});
it('MM-T2050 Username cannot be blank', () => {
// # Clear the username textfield contents
cy.get('#usernameEdit').click();
cy.get('#username').clear();
cy.uiSave();
// * Check if element is present and contains expected text values
cy.get('#clientError').should('be.visible').should('contain', 'Username must begin with a letter, and contain between 3 to 22 lowercase characters made up of numbers, letters, and the symbols \'.\', \'-\', and \'_\'.');
// # Click "x" button to close Profile modal
cy.uiClose();
});
it('MM-T2051 Username min 3 characters', () => {
// # Edit the username field
cy.get('#usernameEdit').click();
// # Add the username to textfield contents
cy.get('#username').clear().type('te');
cy.uiSave();
// * Check if element is present and contains expected text values
cy.get('#clientError').should('be.visible').should('contain', 'Username must begin with a letter, and contain between 3 to 22 lowercase characters made up of numbers, letters, and the symbols \'.\', \'-\', and \'_\'.');
// # Click "x" button to close Profile modal
cy.uiClose();
});
it('MM-T2052 Username already taken', () => {
// # Edit the username field
cy.get('#usernameEdit').click();
// # Add the username to textfield contents
cy.get('#username').clear().type(otherUser.username);
cy.uiSave();
// * Check if element is present and contains expected text values
cy.get('#serverError').should('be.visible').should('contain', 'An account with that username already exists.');
// # Click "x" button to close Profile modal
cy.uiClose();
});
it('MM-T2053 Username w/ dot, dash, underscore still searches', () => {
let tempUser;
// # Create a temporary user
cy.apiCreateUser({prefix: 'temp'}).then(({user: user1}) => {
tempUser = user1;
cy.apiAddUserToTeam(testTeam.id, tempUser.id).then(() => {
cy.apiAddUserToChannel(testChannel.id, tempUser.id);
});
// # Login the temporary user
cy.apiLogin(tempUser);
cy.visit(offTopicUrl);
cy.uiOpenProfileModal();
// # Step 1
// # Edit the username field
cy.get('#usernameEdit').click();
// # Step 2
// # Add the username to textfield contents
const newTempUserName = 'a-' + tempUser.username;
cy.get('#username').clear().type(newTempUserName);
cy.uiSaveAndClose();
// # Step 3
// * Verify that we've logged in as the temp user
cy.visit(offTopicUrl);
cy.uiOpenUserMenu().findByText(`@${newTempUserName}`);
cy.uiGetSetStatusButton().click();
// # Step 4
const text = `${newTempUserName} test message!`;
// # Post the user name mention declared earlier
cy.postMessage(text);
// # Click on the @ button
cy.uiGetRecentMentionButton().should('be.visible').click();
cy.get('#search-items-container').should('be.visible').within(() => {
// * Ensure that the mentions are visible in the RHS
cy.findByText(newTempUserName);
cy.findByText(`${newTempUserName} test message!`);
});
// # Click on the @ button to toggle off
cy.uiGetRecentMentionButton().should('be.visible').click();
});
});
it('MM-T2054 Username cannot start with dot, dash, or underscore', () => {
// # Edit the username field
cy.get('#usernameEdit').click();
const prefixes = [
'.',
'-',
'_',
];
for (const prefix of prefixes) {
// # Add username to textfield contents
cy.get('#username').clear().type(prefix).type('{backspace}.').type(otherUser.username);
cy.uiSave();
// * Check if element is present and contains expected text values
cy.get('#clientError').should('be.visible').should('contain', 'Username must begin with a letter, and contain between 3 to 22 lowercase characters made up of numbers, letters, and the symbols \'.\', \'-\', and \'_\'.');
}
// # Click "x" button to close Profile modal
cy.uiClose();
});
it('MM-T2055 Usernames that are reserved', () => {
// # Edit the username field
cy.get('#usernameEdit').click();
const usernames = [
'all',
'channel',
'here',
'matterbot',
];
for (const username of usernames) {
// # Add username to textfield contents
cy.get('#username').clear().type(username);
cy.uiSave();
// * Check if element is present and contains expected text values
cy.get('#clientError').should('be.visible').should('contain', 'This username is reserved, please choose a new one.');
}
// # Click "x" button to close Profile modal
cy.uiClose();
});
it('MM-T2056 Username changes when viewed by other user', () => {
cy.apiLogin(testUser);
cy.visit(offTopicUrl);
// # Post a message in off-topic
cy.postMessage('Testing username update');
// # Login as other user
cy.apiLogin(otherUser);
cy.visit(offTopicUrl);
// # Get last post in off-topic for verifying username
cy.getLastPostId().then((postId) => {
cy.get(`#post_${postId}`).within(() => {
// # Open profile popover
cy.get('.user-popover').click();
});
// * Verify username in profile popover
cy.get('#user-profile-popover').within(() => {
cy.get('#userPopoverUsername').should('be.visible').and('contain', `${testUser.username}`);
});
});
// # Login as test user
cy.apiLogin(testUser);
cy.visit(offTopicUrl);
// # Open account settings modal
cy.uiOpenProfileModal();
// # Open Full Name section
cy.get('#usernameDesc').click();
const randomId = getRandomId();
// # Save username with a randomId
cy.get('#username').clear().type(`${otherUser.username}-${randomId}`);
// # save form
cy.uiSave();
cy.apiLogin(otherUser);
cy.visit(offTopicUrl);
// # Get last post in off-topic for verifying username
cy.getLastPostId().then((postId) => {
cy.get(`#post_${postId}`).within(() => {
cy.get('.user-popover').click();
});
// * Verify that new username is in profile popover
cy.get('#user-profile-popover').within(() => {
cy.get('#userPopoverUsername').should('be.visible').and('contain', `${otherUser.username}-${randomId}`);
});
});
});
});

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

@@ -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 @account_setting
describe('Profile > Security > View Access History', () => {
before(() => {
// # Login as new user and visit off-topic
cy.apiInitSetup({loginAfter: true}).then(({offTopicUrl}) => {
cy.visit(offTopicUrl);
});
});
beforeEach(() => {
// # Go to Profile
cy.uiOpenProfileModal('Security');
// * Check that the Security tab is loaded
cy.get('#securityButton').should('be.visible');
// # Click the Security tab
cy.get('#securityButton').click();
});
it('MM-T2087 View Access History', () => {
// # Click "View Access History" link
cy.findByText('View Access History').should('be.visible').click();
// * Check that the Access History modal and table are visible
cy.get('#accessHistoryModalLabel').should('be.visible');
cy.get('.modal-body table').should('be.visible');
// * Check that the Access History table has the expected length
cy.get('.modal-body table thead tr th span').should('be.visible').should('have.length', 4);
// * Check that the Access History table header has the expected columns
cy.get('.modal-body table thead tr th span').eq(0).should('be.visible').should('contain', 'Timestamp');
cy.get('.modal-body table thead tr th span').eq(1).should('be.visible').should('contain', 'Action');
cy.get('.modal-body table thead tr th span').eq(2).should('be.visible').should('contain', 'IP Address');
cy.get('.modal-body table thead tr th span').eq(3).should('be.visible').should('contain', 'Session ID');
// * Check that the Access History table body is visible and not empty
cy.findByTestId('auditTableBody').should('be.visible').should('not.empty');
});
});

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

@@ -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 @account_setting
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('Profile > Security > View and Log Out of Active Sessions', () => {
const platforms = [
'Linux',
'Macintosh',
'Windows',
'Native Desktop App',
'iPhone Native App',
'Android Native App',
'iPhone Native Classic App',
'Android Native Classic App',
];
const platformRegex = new RegExp(`${platforms.join('|')}`, 'g');
let testUser: Cypress.UserProfile;
before(() => {
// # Login as new user and visit off-topic
cy.apiInitSetup({loginAfter: true}).then(({offTopicUrl, user}) => {
testUser = user;
cy.visit(offTopicUrl);
// # Go to Profile
cy.uiOpenProfileModal('Security');
// * Check that the Security tab is loaded
cy.get('#securityButton').should('be.visible');
// # Click the Security tab
cy.get('#securityButton').click();
});
});
it('MM-T2088 View and Logout of Active Sessions (Se)', () => {
// # Go to "View and Logout of Active Sessions"
cy.findByText('View and Log Out of Active Sessions').should('be.visible').click();
// * Verify an appropriate platform is shown
cy.get('.report__platform').contains(platformRegex);
// # Click "More info" for the login session
cy.get('.report__info a').should('be.visible').and('have.text', 'More info').click();
// * Verify info is displayed
cy.get('.report__info').should('contain', 'Last activity:').
and('contain', 'First time active:').
and('contain', 'OS:').
and('contain', 'Browser:').
and('contain', 'Session ID:');
// # Click "Log Out" to log out of the specified session
cy.findByText('Log Out').click();
// * Verify we have been logged out, and we can log back in
cy.uiLogin(testUser);
// * Verify we have successfully logged back in
cy.get('#channel_view', {timeout: TIMEOUTS.ONE_MIN}).should('be.visible');
});
});

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

@@ -0,0 +1,154 @@
// 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 @account_setting
import moment from 'moment-timezone';
import * as TIMEOUTS from '../../../../fixtures/timeouts';
describe('Profile', () => {
let siteName: string;
let testUser: Cypress.UserProfile;
let offTopic: string;
before(() => {
cy.apiGetConfig().then(({config}) => {
siteName = config.TeamSettings.SiteName;
});
// # Login as new user and visit off-topic
cy.apiInitSetup({loginAfter: true}).then(({user, offTopicUrl}) => {
testUser = user;
offTopic = offTopicUrl;
cy.visit(offTopicUrl);
});
});
beforeEach(() => {
// # Reload the page to help run each test cleanly
cy.reload();
// # Go to Profile
cy.uiOpenProfileModal('Security');
// * Check that the Security tab is loaded
cy.get('#securityButton').should('be.visible');
// # Click the Security tab
cy.get('#securityButton').click();
// # Click "Edit" to the right of "Password"
cy.get('#passwordEdit').should('be.visible').click();
});
it('MM-T2085 Password: Valid values in password change fields allow the form to save successfully', () => {
// # Enter valid values in password change fields
enterPasswords(testUser.password, 'passwd', 'passwd');
// # Save the settings
cy.uiSave();
// * Check that there are no errors
cy.get('#clientError').should('not.exist');
cy.get('#serverError').should('not.exist');
});
it('MM-T2082 Password: New password confirmation mismatch produces error', () => {
// # Enter mismatching passwords for new password and confirm fields
enterPasswords(testUser.password, 'newPW', 'NewPW');
// # Save
cy.uiSave();
// * Verify for error message: "The new passwords you entered do not match."
cy.get('#clientError').should('be.visible').should('have.text', 'The new passwords you entered do not match.');
});
it('MM-T2083 Password: Too few characters in new password produces error', () => {
// # Enter a New password two letters long
enterPasswords(testUser.password, 'pw', 'pw');
// # Save
cy.uiSave();
// * Verify for error message: "Must be 5-64 characters long."
cy.get('#clientError').should('be.visible').should('have.text', 'Must be 5-64 characters long.');
});
it('MM-T2084 Password: Cancel out of password changes causes no changes to be made', () => {
// # Enter new valid passwords
enterPasswords(testUser.password, 'newPasswd', 'newPasswd');
// # Click 'Cancel'
cy.uiCancel();
// * Check that user is no longer in password edit page to verify the 'Cancel' action
cy.get('#currentPassword').should('not.exist');
cy.get('#passwordEdit').should('be.visible');
// # Logout
cy.apiLogout();
// * Verify that user cannot login with the cancelled password
cy.get('#input_loginId').type(testUser.username);
cy.get('#input_password-input').type('newPasswd');
cy.get('#saveSetting').should('not.be.disabled').click();
cy.findByText('The email/username or password is invalid.').should('be.visible');
// * Verify that user can successfully login with the old password
cy.apiLogin(testUser);
cy.visit(offTopic);
cy.get('#channelHeaderTitle').should('contain', 'Off-Topic');
});
it('MM-T2086 Password: Timestamp and email', () => {
// # Enter valid values in password change fields
enterPasswords(testUser.password, 'passwd', 'passwd');
// # Get current date
const now = moment(Date.now());
// # Save the settings
cy.uiSave();
// # Create expected date and time formats
const date = now.format('MMM DD, YYYY');
const time = now.format('hh:mm A');
// # Create expected timestamp
const timestamp = `Last updated ${date} at ${time}`;
// * Verify that password description field contains valid timestamp
cy.get('#passwordDesc').should('have.text', timestamp);
// # Wait for the mail to be sent out.
cy.wait(TIMEOUTS.FIVE_SEC);
cy.getRecentEmail(testUser).then(({subject}) => {
// * Verify the subject
expect(subject).to.equal(
`[${siteName}] Your password has been updated`,
);
});
});
});
function enterPasswords(currentPassword, newPassword, confirmPassword) {
// # Enter Current password
cy.get('#currentPassword').should('be.visible').type(currentPassword);
// # Enter New password
cy.get('#newPassword').should('be.visible').type(newPassword);
// # Retype New password incorrectly
cy.get('#confirmPassword').should('be.visible').type(confirmPassword);
}