snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 1s
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 1s
This commit is contained in:
@@ -0,0 +1,407 @@
|
||||
// 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 @channel @channel_settings
|
||||
|
||||
import {getRandomId} from '@/utils';
|
||||
|
||||
describe('Channel Settings', () => {
|
||||
let testTeam: Cypress.Team;
|
||||
let firstUser: Cypress.UserProfile;
|
||||
let addedUsersChannel: Cypress.Channel;
|
||||
let username: string;
|
||||
let groupId: string;
|
||||
const usernames: string[] = [];
|
||||
|
||||
const users: Cypress.UserProfile[] = [];
|
||||
|
||||
before(() => {
|
||||
// Require a license for groups
|
||||
cy.apiRequireLicense();
|
||||
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
firstUser = user;
|
||||
const teamId = testTeam.id;
|
||||
|
||||
// # Add 10 users
|
||||
for (let i = 0; i < 10; i++) {
|
||||
cy.apiCreateUser().then(({user: newUser}) => {
|
||||
users.push(newUser);
|
||||
cy.apiAddUserToTeam(teamId, newUser.id);
|
||||
});
|
||||
}
|
||||
cy.apiCreateChannel(teamId, 'channel-test', 'Channel').then(({channel}) => {
|
||||
addedUsersChannel = channel;
|
||||
});
|
||||
|
||||
// # Change permission so that regular users can't add team members
|
||||
cy.apiGetRolesByNames(['team_user']).then(({roles}) => {
|
||||
if (roles?.length) {
|
||||
const role = roles[0];
|
||||
const permissions = role.permissions.filter((permission: string) => {
|
||||
return !(['add_user_to_team'].includes(permission));
|
||||
});
|
||||
|
||||
if (permissions.length !== role.permissions.length) {
|
||||
cy.apiPatchRole(role.id, {permissions});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cy.apiLogin(firstUser);
|
||||
}).then(() => {
|
||||
groupId = getRandomId();
|
||||
cy.apiCreateCustomUserGroup(`group${groupId}`, `group${groupId}`, [users[0].id, users[1].id]);
|
||||
});
|
||||
});
|
||||
|
||||
// it('MM-T859_1 Single User: Usernames are links, open profile popovers', () => {
|
||||
// // # Create and visit new channel
|
||||
// cy.apiCreateChannel(testTeam.id, 'channel-test', 'Channel').then(({channel}) => {
|
||||
// cy.visit(`/${testTeam.name}/channels/${channel.name}`);
|
||||
|
||||
// // # Add users to channel
|
||||
// addNumberOfUsersToChannel(1, false);
|
||||
|
||||
// cy.getLastPostId().then((id) => {
|
||||
// // * The system message should contain 'added to the channel by you'
|
||||
// cy.get(`#postMessageText_${id}`).should('contain', 'added to the channel by you');
|
||||
|
||||
// // # Verify username link
|
||||
// verifyMentionedUserAndProfilePopover(id);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('MM-T859_2 Combined Users: Usernames are links, open profile popovers', () => {
|
||||
// // # Create and visit new channel
|
||||
// cy.apiCreateChannel(testTeam.id, 'channel-test', 'Channel').then(({channel}) => {
|
||||
// cy.visit(`/${testTeam.name}/channels/${channel.name}`);
|
||||
|
||||
// addNumberOfUsersToChannel(3, false);
|
||||
|
||||
// cy.getLastPostId().then((id) => {
|
||||
// cy.get(`#postMessageText_${id}`).should('contain', '2 others were added to the channel by you');
|
||||
|
||||
// // # Click "2 others" to expand more users
|
||||
// cy.get(`#post_${id}`).find('.markdown__paragraph-inline').siblings('a').first().click().then(() => {
|
||||
// // # Verify each username link
|
||||
// verifyMentionedUserAndProfilePopover(id);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
it('MM-T856_1 Add existing users to public channel from drop-down > Add Members', () => {
|
||||
// # Visit the add users channel
|
||||
cy.visit(`/${testTeam.name}/channels/${addedUsersChannel.name}`);
|
||||
|
||||
// # Open channel menu and click 'Add Members'
|
||||
cy.uiOpenChannelMenu('Members');
|
||||
cy.uiGetButton('Add').click();
|
||||
|
||||
// * Assert that modal appears
|
||||
cy.get('#addUsersToChannelModal').should('be.visible');
|
||||
|
||||
// # Type into the input box to search for a user
|
||||
cy.get('#selectItems input').typeWithForce('user');
|
||||
|
||||
// # First add one user in order to see them disappearing from the list
|
||||
cy.get('#multiSelectList > div').not(':contains("Already in channel")').first().then((el) => {
|
||||
const childNodes = Array.from(el[0].childNodes);
|
||||
childNodes.map((child: ChildNode) => usernames.push((child as HTMLElement).innerText));
|
||||
|
||||
// # Get username from text for comparison
|
||||
username = usernames.toString().match(/\w+/g)![0];
|
||||
cy.get('#multiSelectList').should('contain', username);
|
||||
|
||||
// # Verify status wrapper is present within the modal list
|
||||
cy.get(el as unknown as string).children().first().should('have.class', 'status-wrapper');
|
||||
|
||||
// # Click to add the first user
|
||||
cy.wrap(el).click();
|
||||
|
||||
// # Verify users list is not visible
|
||||
cy.get('#multiSelectList').should('not.exist');
|
||||
|
||||
// # Click 'Add' button
|
||||
cy.uiGetButton('Add').click();
|
||||
cy.get('#addUsersToChannelModal').should('not.exist');
|
||||
});
|
||||
|
||||
// # Verify that the last system post also contains the username
|
||||
cy.getLastPostId().then((id) => {
|
||||
cy.get(`#postMessageText_${id}`).should('contain', `${username} added to the channel by you.`);
|
||||
});
|
||||
|
||||
// Add two more users
|
||||
addNumberOfUsersToChannel(2, false);
|
||||
|
||||
// Verify that the system post reflects the number of added users
|
||||
cy.getLastPostId().then((id) => {
|
||||
cy.get(`#postMessageText_${id}`).should('contain', 'added to the channel by you');
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T856_2 Existing users cannot be added to public channel from drop-down > Add Members', () => {
|
||||
cy.apiAdminLogin();
|
||||
|
||||
// # Visit the add users channel
|
||||
cy.visit(`/${testTeam.name}/channels/${addedUsersChannel.name}`);
|
||||
|
||||
// # Verify that the system message for adding users displays
|
||||
cy.getLastPostId().then((id) => {
|
||||
cy.get(`#postMessageText_${id}`).should('contain', `added to the channel by @${firstUser.username}`);
|
||||
});
|
||||
|
||||
// Visit off topic where all users are added
|
||||
cy.visit(`/${testTeam.name}/channels/off-topic`);
|
||||
|
||||
// # Open channel menu and click 'Add Members'
|
||||
cy.uiOpenChannelMenu('Members');
|
||||
cy.uiGetButton('Add').click();
|
||||
|
||||
// * Assert that modal appears
|
||||
cy.get('#addUsersToChannelModal').should('be.visible');
|
||||
|
||||
// # Type into the input box to search for already added user
|
||||
cy.get('#selectItems input').typeWithForce(firstUser.username);
|
||||
|
||||
// * Verify user list exist
|
||||
cy.get('#multiSelectList').should('exist').within(() => {
|
||||
cy.findByText('Already in channel').should('be.visible');
|
||||
});
|
||||
cy.get('body').type('{esc}');
|
||||
});
|
||||
|
||||
it('Add group members to channel', () => {
|
||||
cy.apiLogin(firstUser);
|
||||
|
||||
// # Create a new channel
|
||||
cy.apiCreateChannel(testTeam.id, 'new-channel', 'New Channel').then(({channel}) => {
|
||||
// # Visit the channel
|
||||
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
|
||||
|
||||
// # Open channel menu and click 'Add Members'
|
||||
cy.uiOpenChannelMenu('Members');
|
||||
cy.uiGetButton('Add').click();
|
||||
|
||||
// * Assert that modal appears
|
||||
cy.get('#addUsersToChannelModal').should('be.visible');
|
||||
|
||||
// # Type 'group'+ id created in beforeAll into the input box
|
||||
cy.get('#selectItems input').typeWithForce(`group${groupId}`);
|
||||
|
||||
// # Click the first row for a number of times
|
||||
// cy.get('#multiSelectList').should('be.visible').first().click();
|
||||
cy.get('#multiSelectList').should('exist').children().first().click();
|
||||
|
||||
// # Click the button "Add" to add user to a channel
|
||||
cy.uiGetButton('Add').click();
|
||||
|
||||
// # Wait for the modal to disappear
|
||||
cy.get('#addUsersToChannelModal').should('not.exist');
|
||||
|
||||
cy.getLastPostId().then((id) => {
|
||||
// * The system message should contain 'added to the channel by you'
|
||||
cy.get(`#postMessageText_${id}`).should('contain', 'added to the channel by you');
|
||||
|
||||
// # Verify username link
|
||||
verifyMentionedUserAndProfilePopover(id);
|
||||
});
|
||||
|
||||
// * Check that the number of channel members is 3
|
||||
cy.get('#channelMemberCountText').
|
||||
should('be.visible').
|
||||
and('have.text', '3');
|
||||
});
|
||||
});
|
||||
|
||||
it('Add group members that are not team members', () => {
|
||||
cy.apiAdminLogin();
|
||||
|
||||
// # Create a new user
|
||||
cy.apiCreateUser().then(({user: newUser}) => {
|
||||
const id = getRandomId();
|
||||
|
||||
// # Create a custom user group
|
||||
cy.apiCreateCustomUserGroup(`newgroup${id}`, `newgroup${id}`, [newUser.id]).then(() => {
|
||||
// # Create a new channel
|
||||
cy.apiCreateChannel(testTeam.id, 'new-group-channel', 'New Group Channel').then(({channel}) => {
|
||||
// # Visit a channel
|
||||
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
|
||||
|
||||
// # Open channel menu and click 'Add Members'
|
||||
cy.uiOpenChannelMenu('Members');
|
||||
cy.uiGetButton('Add').click();
|
||||
|
||||
// * Assert that modal appears
|
||||
cy.get('#addUsersToChannelModal').should('be.visible');
|
||||
|
||||
// # Type 'group' into the input box
|
||||
cy.get('#selectItems input').typeWithForce(`newgroup${id}`);
|
||||
|
||||
// # Click the first row for a number of times
|
||||
// cy.get('#multiSelectList').should('be.visible').first().click();
|
||||
cy.get('#multiSelectList').should('exist').children().first().click();
|
||||
|
||||
// * Check you get a warning when adding a non team member
|
||||
cy.findByTestId('teamWarningBanner').should('contain', '1 user was not selected because they are not a part of this team');
|
||||
|
||||
// * Check the correct username is appearing in the team invite banner
|
||||
cy.findByTestId('teamWarningBanner').should('contain', `@${newUser.username}`);
|
||||
|
||||
// # Click the button "Add" to add user to a channel
|
||||
cy.uiGetButton('Cancel').click();
|
||||
|
||||
// # Wait for the modal to disappear
|
||||
cy.get('#addUsersToChannelModal').should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Add group members and guests that are not team members', () => {
|
||||
cy.apiAdminLogin();
|
||||
|
||||
// # Create a new user
|
||||
cy.apiCreateUser().then(({user: newUser}) => {
|
||||
// # Create a guest user
|
||||
cy.apiCreateGuestUser({}).then(({guest}) => {
|
||||
const id = getRandomId();
|
||||
|
||||
// # Create a custom user group
|
||||
cy.apiCreateCustomUserGroup(`guestgroup${id}`, `guestgroup${id}`, [guest.id, newUser.id]).then(() => {
|
||||
// # Create a new channel
|
||||
cy.apiCreateChannel(testTeam.id, 'group-guest-channel', 'Channel').then(({channel}) => {
|
||||
// # Visit a channel
|
||||
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
|
||||
|
||||
// # Open channel menu and click 'Add Members'
|
||||
cy.uiOpenChannelMenu('Members');
|
||||
cy.uiGetButton('Add').click();
|
||||
|
||||
// * Assert that modal appears
|
||||
cy.get('#addUsersToChannelModal').should('be.visible');
|
||||
|
||||
// # Type 'group' into the input box
|
||||
cy.get('#selectItems input').typeWithForce(`guestgroup${id}`);
|
||||
|
||||
// # Click the first row for a number of times
|
||||
// cy.get('#multiSelectList').should('be.visible').first().click();
|
||||
cy.get('#multiSelectList').should('exist').children().first().click();
|
||||
|
||||
// * Check you get a warning when adding a non team member
|
||||
cy.findByTestId('teamWarningBanner').should('contain', '2 users were not selected because they are not a part of this team');
|
||||
|
||||
// * Check the correct username is appearing in the invite to team portion
|
||||
cy.findByTestId('teamWarningBanner').should('contain', `@${newUser.username}`);
|
||||
|
||||
// * Check the guest username is in the warning message and won't be added to the team
|
||||
cy.findByTestId('teamWarningBanner').should('contain', `@${guest.username} is a guest user`);
|
||||
|
||||
// # Click the button "Add" to add user to a channel
|
||||
cy.uiGetButton('Cancel').click();
|
||||
|
||||
// # Wait for the modal to disappear
|
||||
cy.get('#addUsersToChannelModal').should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('User doesn\'t have permission to add user to team', () => {
|
||||
cy.apiAdminLogin();
|
||||
|
||||
// # Create a new user
|
||||
cy.apiCreateUser().then(({user: newUser}) => {
|
||||
const id = getRandomId();
|
||||
|
||||
// # Create a custom user group
|
||||
cy.apiCreateCustomUserGroup(`newgroup${id}`, `newgroup${id}`, [newUser.id]).then(() => {
|
||||
// # Create a new channel
|
||||
cy.apiCreateChannel(testTeam.id, 'new-group-channel', 'Channel').then(({channel}) => {
|
||||
cy.apiLogin(firstUser);
|
||||
|
||||
// # Visit a channel
|
||||
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
|
||||
|
||||
// # Open channel menu and click 'Add Members'
|
||||
cy.uiOpenChannelMenu('Members');
|
||||
cy.uiGetButton('Add').click();
|
||||
|
||||
// * Assert that modal appears
|
||||
cy.get('#addUsersToChannelModal').should('be.visible');
|
||||
|
||||
// # Type 'group' into the input box
|
||||
cy.get('#selectItems input').typeWithForce(`newgroup${id}`);
|
||||
|
||||
// # Click the first row for a number of times
|
||||
// cy.get('#multiSelectList').should('be.visible').first().click();
|
||||
cy.get('#multiSelectList').should('exist').children().first().click();
|
||||
|
||||
// * Check you get a warning when adding a non team member
|
||||
cy.findByTestId('teamWarningBanner').should('contain', '1 user was not selected because they are not a part of this team');
|
||||
|
||||
// * Check the correct username is appearing in the team invite banner
|
||||
cy.findByTestId('teamWarningBanner').should('contain', `@${newUser.username}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function verifyMentionedUserAndProfilePopover(postId: string) {
|
||||
cy.get(`#post_${postId}`).find('.mention-link').each(($el) => {
|
||||
// # Get username from each mentioned link
|
||||
const userName = $el[0].innerHTML;
|
||||
|
||||
// # Click each username link
|
||||
cy.wrap($el).click();
|
||||
|
||||
// * Profile popover should be visible
|
||||
cy.get('div.user-profile-popover').should('be.visible');
|
||||
|
||||
// * The username in the popover the same as the username link for each user
|
||||
cy.get('div.user-profile-popover').should('contain', userName);
|
||||
cy.get('button.closeButtonRelativePosition').click();
|
||||
|
||||
// Click anywhere to close profile popover
|
||||
cy.get('#channelHeaderInfo').click();
|
||||
});
|
||||
}
|
||||
|
||||
function addNumberOfUsersToChannel(num = 1, allowExisting = false) {
|
||||
// # Open channel menu and click 'Add Members'
|
||||
cy.uiOpenChannelMenu('Members');
|
||||
cy.uiGetButton('Add').click();
|
||||
cy.get('#addUsersToChannelModal').should('be.visible');
|
||||
|
||||
// * Assert that modal appears
|
||||
// # Click the first row for a number of times
|
||||
Cypress._.times(num, () => {
|
||||
cy.get('#selectItems input').typeWithForce('user');
|
||||
|
||||
// cy.get('#multiSelectList').should('be.visible').first().click();
|
||||
if (allowExisting) {
|
||||
cy.get('#multiSelectList').should('exist').children().first().click();
|
||||
} else {
|
||||
cy.get('#multiSelectList').should('exist').children().not(':contains("Already in channel")').first().click();
|
||||
}
|
||||
});
|
||||
|
||||
// # Click the button "Add" to add user to a channel
|
||||
cy.uiGetButton('Add').click();
|
||||
|
||||
// # Wait for the modal to disappear
|
||||
cy.get('#addUsersToChannelModal').should('not.exist');
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// 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 @channel_settings
|
||||
// node run_tests.js --group='@channel_settings'
|
||||
|
||||
import type {ChannelType} from '@mattermost/types/channels';
|
||||
|
||||
import * as TIMEOUTS from '@/fixtures/timeouts';
|
||||
import {getRandomId} from '@/utils';
|
||||
|
||||
describe('Channel Settings', () => {
|
||||
let testTeam: Cypress.Team;
|
||||
let user1: Cypress.UserProfile;
|
||||
let admin: Cypress.UserProfile;
|
||||
|
||||
before(() => {
|
||||
cy.apiGetMe().then(({user: adminUser}) => {
|
||||
admin = adminUser;
|
||||
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
user1 = user;
|
||||
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T1808 Hover effect exists to add a channel description / header (when not already present)', () => {
|
||||
// # Create a new public channel and then private channel
|
||||
['O', 'P'].forEach((channelType) => {
|
||||
cy.apiCreateChannel(testTeam.id, `chan${getRandomId()}`, 'chan', channelType as ChannelType).then(({channel}) => {
|
||||
// # Go to new channel
|
||||
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
|
||||
|
||||
// * Test hovering over the header with public and private channel
|
||||
hoverOnChannelDescriptionAndVerifyBehavior();
|
||||
});
|
||||
});
|
||||
|
||||
// # Create DM with admin and user 1
|
||||
cy.apiCreateDirectChannel([admin.id, user1.id]).then(() => {
|
||||
// # Go to DM
|
||||
cy.visit(`/${testTeam.name}/messages/@${user1.username}`);
|
||||
|
||||
// * Test hovering over the header with DM
|
||||
hoverOnChannelDescriptionAndVerifyBehavior();
|
||||
});
|
||||
|
||||
// # Create another user and add to the team
|
||||
cy.apiCreateUser().then(({user: user2}) => {
|
||||
cy.apiAddUserToTeam(testTeam.id, user2.id).then(() => {
|
||||
// # Create a GM with admin, user1 and user 2
|
||||
cy.apiCreateGroupChannel([user2.id, user1.id, admin.id]).then(({channel}) => {
|
||||
// # Visit the channel using the name using the channels route
|
||||
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
|
||||
|
||||
// * Test hovering over the header with GM
|
||||
hoverOnChannelDescriptionAndVerifyBehavior();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function hoverOnChannelDescriptionAndVerifyBehavior() {
|
||||
const channelDescriptionText = `test description ${getRandomId()}`;
|
||||
|
||||
// # Wait a little for channel to load
|
||||
cy.wait(TIMEOUTS.ONE_SEC);
|
||||
|
||||
// # Scan within channel header description area
|
||||
cy.get('#channelHeaderDescription').should('be.visible').find('span').invoke('show').click({multiple: true, force: true});
|
||||
|
||||
// # Scan inside the channel header modal
|
||||
cy.get('.a11y__modal.modal-dialog').should('be.visible').within(() => {
|
||||
// # Enter a channel description
|
||||
cy.findByTestId('edit_textbox').should('exist').clear().type(channelDescriptionText);
|
||||
|
||||
// # Click on save
|
||||
cy.findByText('Save').should('be.visible').click();
|
||||
});
|
||||
|
||||
cy.get('#channelHeaderDescription').should('be.visible').within(() => {
|
||||
// * Verify that new channel header is set and click it
|
||||
cy.findAllByText(channelDescriptionText).should('be.visible').click({multiple: true, force: true});
|
||||
});
|
||||
|
||||
// * Check clicking on it doesn't open the edit modal once again
|
||||
cy.get('.a11y__modal.modal-dialog').should('not.exist');
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
// 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 @channel @channel_settings
|
||||
|
||||
import * as TIMEOUTS from '@/fixtures/timeouts';
|
||||
import {getRandomId} from '@/utils';
|
||||
|
||||
describe('Channel routing', () => {
|
||||
let testTeam: Cypress.Team;
|
||||
let testUser: Cypress.UserProfile;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
// # Login as test user and go to town square
|
||||
cy.apiLogin(testUser);
|
||||
cy.visit(`/${team.name}/channels/town-square`);
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T884_1 Renaming channel name validates against two user IDs being used in URL', () => {
|
||||
// # Create new test channel
|
||||
cy.uiCreateChannel({name: 'Test__Channel'});
|
||||
|
||||
// # Open channel settings modal from channel header dropdown
|
||||
cy.get('#channelHeaderDropdownButton').click();
|
||||
cy.findByText('Channel Settings').click();
|
||||
|
||||
// # Assert if the channel settings modal is present
|
||||
cy.get('.ChannelSettingsModal').should('be.visible');
|
||||
|
||||
// # Click on the URL input button to edit the URL
|
||||
cy.get('.url-input-button').should('be.visible').click({force: true});
|
||||
|
||||
// # Type the two 26 character strings with 2 underscores between them
|
||||
cy.get('.url-input-container input').clear().type('uzsfmtmniifsjgesce4u7yznyh__uzsfmtmniifsjgesce5u7yznyh', {force: true}).wait(TIMEOUTS.HALF_SEC);
|
||||
|
||||
// # Assert the error occurred with the appropriate message
|
||||
cy.get('.SaveChangesPanel').should('contain', 'There are errors in the form above');
|
||||
cy.get('.url-input-error').should('contain', 'User IDs are not allowed in channel URLs.');
|
||||
|
||||
// # Reset the changes so modal can be closed
|
||||
cy.get('[data-testid="SaveChangesPanel__cancel-btn"]').click();
|
||||
|
||||
// # Close the modal
|
||||
cy.get('.GenericModal .modal-header button[aria-label="Close"]').click();
|
||||
});
|
||||
|
||||
it('MM-T884_2 Creating new channel validates against two user IDs being used as channel name', () => {
|
||||
// # click on create public channel
|
||||
cy.uiBrowseOrCreateChannel('Create new channel');
|
||||
|
||||
// * Verify that the new channel modal is visible
|
||||
cy.get('#new-channel-modal').should('be.visible').within(() => {
|
||||
// # Add the new channel name with invalid name and press Create Channel
|
||||
cy.get('#input_new-channel-modal-name').type('uzsfmtmniifsjgesce4u7yznyh__uzsfmtmniifsjgesce5u7yznyh', {force: true}).wait(TIMEOUTS.HALF_SEC);
|
||||
cy.findByText('Create channel').should('be.visible').click();
|
||||
|
||||
// * Assert the error occurred with the appropriate message
|
||||
cy.get('.genericModalError').should('be.visible').within(() => {
|
||||
cy.findByText('Channel names can\'t be in a hexadecimal format. Please enter a different channel name.');
|
||||
});
|
||||
|
||||
// # Close the create channel modal
|
||||
cy.uiCancelButton().click();
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T884_3 Creating a new channel validates against gm-like names being used as channel name', () => {
|
||||
// # click on create public channel
|
||||
cy.uiBrowseOrCreateChannel('Create new channel');
|
||||
|
||||
// * Verify that the new channel modal is visible
|
||||
cy.findByRole('dialog', {name: 'Create a new channel'}).within(() => {
|
||||
// # Add the new channel name with invalid name and press Create Channel
|
||||
cy.findByPlaceholderText('Enter a name for your new channel').type('71b03afcbb2d503d49f87f057549c43db4e19f92', {force: true}).wait(TIMEOUTS.HALF_SEC);
|
||||
cy.uiGetButton('Create channel').click();
|
||||
|
||||
// * Assert the error occurred with the appropriate message
|
||||
cy.get('.genericModalError').should('be.visible').within(() => {
|
||||
cy.findByText('Channel names can\'t be in a hexadecimal format. Please enter a different channel name.');
|
||||
});
|
||||
|
||||
// # Close the create channel modal
|
||||
cy.uiCancelButton().click();
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T883 Channel URL validation for spaces between characters', () => {
|
||||
const firstWord = getRandomId(26);
|
||||
const secondWord = getRandomId(26);
|
||||
const channelName = 'test-channel-' + getRandomId(8);
|
||||
|
||||
// # Create a new test channel and navigate to it
|
||||
cy.apiCreateChannel(testTeam.id, channelName, 'Test Channel for URL Validation').then(({channel}) => {
|
||||
cy.apiAddUserToChannel(channel.id, testUser.id);
|
||||
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
|
||||
});
|
||||
|
||||
// # Open channel settings modal from channel header dropdown
|
||||
cy.get('#channelHeaderDropdownButton').click();
|
||||
cy.findByText('Channel Settings').click();
|
||||
|
||||
// # Change the channel name to {26 alphanumeric characters}[insert 2 spaces]{26 alphanumeric characters}
|
||||
// i.e. a total of 54 characters separated by 2 spaces
|
||||
cy.get('#input_channel-settings-name').clear().type(`${firstWord}${Cypress._.repeat(' ', 2)}${secondWord}`);
|
||||
|
||||
// # Since channel name no longer auto-updates URL, manually set the URL to test the space handling
|
||||
cy.get('.url-input-button').click();
|
||||
cy.get('.url-input-container input').clear().type(`${firstWord}${Cypress._.repeat(' ', 2)}${secondWord}`);
|
||||
cy.get('.url-input-container button.url-input-button').click();
|
||||
|
||||
// # Save changes
|
||||
cy.get('[data-testid="SaveChangesPanel__save-btn"]').click();
|
||||
|
||||
// * Verify changes are saved
|
||||
cy.get('.SaveChangesPanel').should('contain', 'Settings saved');
|
||||
|
||||
// # Close the modal
|
||||
cy.get('.GenericModal .modal-header button[aria-label="Close"]').click();
|
||||
|
||||
// * The channel name should be updated to the characters you typed with only 1 space between the characters (extra spaces are trimmed)
|
||||
cy.get('#channelHeaderTitle').contains(`${firstWord} ${secondWord}`);
|
||||
|
||||
// * The channel URL should be updated to the characters you typed, separated by 2 dashes
|
||||
cy.url().should('equal', `${Cypress.config('baseUrl')}/${testTeam.name}/channels/${firstWord}${Cypress._.repeat('-', 2)}${secondWord}`);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,90 @@
|
||||
// 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 @channel_settings
|
||||
|
||||
describe('Channel settings', () => {
|
||||
let mainUser: Cypress.UserProfile;
|
||||
let otherUser: Cypress.UserProfile;
|
||||
let myTeam: Cypress.Team;
|
||||
|
||||
// # Ensure a list of channel names that will be alphabetically sorted
|
||||
const channelNames = new Array(20).fill(1).map((value, index) => `scroll${index}`);
|
||||
|
||||
before(() => {
|
||||
// # Create a user and a team (done by apiInitSetup)
|
||||
cy.apiInitSetup().then(({team, user: firstUser}) => {
|
||||
mainUser = firstUser;
|
||||
myTeam = team;
|
||||
|
||||
// # Create another user and add it to the same team
|
||||
cy.apiCreateUser().then(({user: secondUser}) => {
|
||||
otherUser = secondUser;
|
||||
cy.apiAddUserToTeam(team.id, secondUser.id);
|
||||
});
|
||||
|
||||
// # Create 20 channels (based on length of channelNames array) to ensure that the channels list is scrollable
|
||||
cy.wrap(channelNames).each((name) => {
|
||||
const displayName = `channel-${name}`;
|
||||
cy.apiCreateChannel(team.id, name.toString(), displayName, 'O', '', '', false).then(({channel}) => {
|
||||
// # Add our 2 created users to each channel so they can both post messages
|
||||
cy.apiAddUserToChannel(channel.id, mainUser.id);
|
||||
cy.apiAddUserToChannel(channel.id, otherUser.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T888 Channel sidebar: More unreads', () => {
|
||||
const firstChannelIndex = 0;
|
||||
const lastChannelIndex = channelNames.length - 1;
|
||||
|
||||
// # Navigate to off-topic channel
|
||||
cy.apiLogin(mainUser);
|
||||
cy.visit(`/${myTeam.name}/channels/off-topic`);
|
||||
|
||||
// # Wait for channels to load
|
||||
cy.get(`#sidebarItem_${channelNames[firstChannelIndex]}`).should('be.visible');
|
||||
|
||||
// # Nudge the scrollbar slightly to make the "More Unreads" pills appear
|
||||
// @hmhealey - They seem to appear automatically on a regular browser, but not when running under Cypress
|
||||
cy.get('#SidebarContainer .simplebar-content-wrapper').scrollTo(0, 1);
|
||||
|
||||
// * The bottom "More Unreads" pill should be visible and the top one should not
|
||||
cy.get('#unreadIndicatorTop').should('not.be.visible');
|
||||
cy.get('#unreadIndicatorBottom').should('be.visible');
|
||||
|
||||
// # Click on the "More Unreads" pill to scroll down to the bottom
|
||||
cy.get('#unreadIndicatorBottom').click();
|
||||
|
||||
// * The list should have scrolled down to the bottom
|
||||
cy.get(`#sidebarItem_${channelNames[firstChannelIndex]}`).should('not.be.visible');
|
||||
cy.get(`#sidebarItem_${channelNames[lastChannelIndex]}`).should('be.visible');
|
||||
|
||||
// * The top "More Unreads" pill should now be visible and the bottom one should not
|
||||
cy.get('#unreadIndicatorTop').should('be.visible');
|
||||
cy.get('#unreadIndicatorBottom').should('not.be.visible');
|
||||
|
||||
// * The "More Unreads" pill should now be visible at the top of the channels list
|
||||
// # Click on the "More Unreads" pill to scroll up to the top
|
||||
cy.get('#unreadIndicatorTop').click();
|
||||
|
||||
// * The list should have scrolled up to the top
|
||||
cy.get(`#sidebarItem_${channelNames[firstChannelIndex]}`).should('be.visible');
|
||||
cy.get(`#sidebarItem_${channelNames[lastChannelIndex]}`).should('not.be.visible');
|
||||
|
||||
// # Scroll somewhere to the middle of the list
|
||||
cy.get('#SidebarContainer .simplebar-content-wrapper').scrollTo(0, 200);
|
||||
|
||||
// * Both "More Unreads" pills should now be visible
|
||||
cy.get('#unreadIndicatorTop').should('be.visible');
|
||||
cy.get('#unreadIndicatorBottom').should('be.visible');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user