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

This commit is contained in:
upstream-mirror
2026-09-16 00:29:55 +05:00
commit 240db4e2a7
15309 changed files with 2173406 additions and 0 deletions

View File

@@ -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');
}

View File

@@ -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');
}

View File

@@ -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}`);
});
});

View File

@@ -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');
});
});