MM61173 - settings modal base creation (#30338)

* MM-61173 - channel settings modal: base modal, initial commit, file creation and base component

* new enhancements to the base modal creation

* revert changes on textbox_links and edit channel header

* fix types and add back unintentioned deleted value

* add the preview textbox component

* extract logic for info tab into its own component

* add the purpose input to the window

* move other component logic to its own component and code clean up

* ability to update channel type

* more advances on the archive channel tab

* fix unit test in textbox

* fix translations

* do not show the archive modal in default channel

* fix issue with url editor not being resetted on undo action

* adjust text and styling for the header and purpose inputs

* remove textboxlinks and use button eye icon

* adjust test and preview button style

* add unit test to channel patch

* move logic from parent modal to info tab component

* fix border issues and focus back to preview textareas

* prevent saving changes when pressing enter when selecting an icon

* enhance input component to cover limits validations and enhances tests

* set default error message for save changes panel

* add props to provide custom value to the buttons

* remove channel input errors on reset button click

* create new component settings textbox

* rename component to advanced textbox and add unit tests

* styling of the info tab and add error state to advanced textbox

* add logic to prevent tab switch with unsaved changes

* adjust url error logic and code clean up

* code clean up and enhance comments

* add char min length to advanced textbox logic

* add the channel settings modal to the new menu

* add new test files and fix reset error

* remove unused error variables

* adjust translations and remove unncesary import

* enhance permissions for archive channels and manage channel settings

* Adjust permission tree so channel admins can convert from private to public

* enhance the test suit around channel conversion type

* fix some e2e tests and solve channel input name issue

* fix unit test by interacting first with the input element

* adjust e2e tests to channel settings modal changes

* remove commented tests and implement pr feedback

* adjust more pr feedback to the code

* more pr feedback enhancements

* further enhancements to tab navigation, and adjust more e2e tests

* remove unused components and fix e2e tests

* revert unnecessary permissions changes

* Add name label to textboxes

* adjust e2e and unit tests

* revert min lenght change value and adjust tests and snapshots

* Channel banner settings (#30721)

* Added channel banner setting header

* Updated section styling

* handled animation

* handled min and max lengths

* cleanup

* color change fix

* general improvements

* Fixed API test

* removed unused param className

* added e2e tests

* test: add channel settings configuration tab test file

* Based on the context, here's a concise commit message for this change:

feat: Add comprehensive tests for ChannelSettingsConfigurationTab

* added some more tests

* CI

* reverted package-lock.json changes in Playwright

* remove extra border from advaced textbox

* adjust styling for name label in advance texbox and restart preview state on modal close

* sync package.lock in playwright

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: Harshil Sharma <harshilsharma63@gmail.com>
Co-authored-by: Harshil Sharma <18575143+harshilsharma63@users.noreply.github.com>
Этот коммит содержится в:
Pablo Vélez
2025-04-23 12:49:54 +02:00
коммит произвёл GitHub
родитель f0dfe1c49f
Коммит 6ae0efd285
84 изменённых файлов: 7479 добавлений и 2464 удалений

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

@@ -88,12 +88,14 @@ describe('Verify Accessibility Support in different sections in Settings and Pro
});
it('MM-T1465_1 Verify Label & Tab behavior in section links', () => {
// * Verify aria-label and tab support in section of Account settings modal
// * Verify tab selection and keyboard navigation in Account settings modal
cy.uiOpenProfileModal('Profile Settings');
cy.findByRole('tab', {name: 'profile settings'}).should('be.visible').focus().should('be.focused');
['profile settings', 'security'].forEach((text) => {
// * Verify aria-label on each tab and it supports navigating to the next tab with arrow keys
cy.focused().should('have.attr', 'aria-label', text).type('{downarrow}');
// * Verify each tab is correctly selected and supports navigating to the next tab with arrow keys
cy.findByRole('tab', {name: text}).
should('have.attr', 'aria-selected', 'true').
type('{downarrow}');
});
cy.uiClose();
@@ -101,8 +103,10 @@ describe('Verify Accessibility Support in different sections in Settings and Pro
cy.uiOpenSettingsModal();
cy.findByRole('tab', {name: 'notifications'}).should('be.visible').focus().should('be.focused');
['notifications', 'display', 'sidebar', 'advanced'].forEach((text) => {
// * Verify aria-label on each tab and it supports navigating to the next tab with arrow keys
cy.focused().should('have.attr', 'aria-label', text).type('{downarrow}');
// * Verify each tab is correctly selected and supports navigating to the next tab with arrow keys
cy.findByRole('tab', {name: text}).
should('have.attr', 'aria-selected', 'true').
type('{downarrow}');
});
});

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

@@ -29,30 +29,39 @@ describe('Channel Settings - Channel Header', () => {
// # Visit the newly created channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Click on the channel name in the channel header to open the channel menu options
cy.get(`[aria-label="${channel.display_name.split('-').join(' ').toLowerCase()} channel menu"]`).click();
// # Select the "Edit Channel Header" option from the dropdown
cy.findByText('Channel Settings').should('be.visible').trigger('mouseover');
cy.findByText('Edit Channel Header').click();
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// * Verify modal is open
cy.get('.ChannelSettingsModal').should('be.visible');
cy.get('#genericModalLabel').should('contain', 'Channel Settings');
// # Type something in the header edit box
cy.get('textarea[placeholder="Edit the Channel Header..."]').clear().type('This is the new header content');
cy.get('#channel_settings_header_textbox').clear().type('This is the new header content');
// * Verify the "Preview" button exists
cy.findByText('Preview').should('be.visible');
// * Verify the "Preview" button exists and is not active
cy.get('#channel_settings_header_textbox').
parents('.AdvancedTextbox').
find('#PreviewInputTextButton').
should('not.have.class', 'active');
// * Verify that before hitting the preview button, the style on the textbox is `display: block`
cy.get('textarea[placeholder="Edit the Channel Header..."]').should('have.css', 'display', 'block');
cy.get('#channel_settings_header_textbox').should('have.css', 'display', 'block');
// # Click the "Preview" button
cy.findByText('Preview').click();
// * Verify the "Preview" button label has changed to "Edit"
cy.findByText('Edit').should('be.visible');
cy.get('#channel_settings_header_textbox').
parents('.AdvancedTextbox').
find('#PreviewInputTextButton').click();
// * Verify that the display is now none on the textbox element
cy.get('textarea[placeholder="Edit the Channel Header..."]').should('have.css', 'display', 'none');
cy.get('#channel_settings_header_textbox').should('have.css', 'display', 'none');
// * Verify the "Preview" button has class active
cy.get('#channel_settings_header_textbox').
parents('.AdvancedTextbox').
find('#PreviewInputTextButton').
should('have.class', 'active');
});
});
});

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

@@ -0,0 +1,361 @@
// 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 {Team} from '@mattermost/types/teams';
import {Channel} from '@mattermost/types/channels';
import {UserProfile} from '@mattermost/types/users';
describe('Channel Settings Modal', () => {
let testTeam: Team;
let testUser: UserProfile;
let testChannel: Channel;
let originalTestChannel: Channel;
before(() => {
// Setup test data
cy.apiInitSetup().then(({team, user}) => {
testTeam = team;
testUser = user;
// Create a test channel
cy.apiCreateChannel(testTeam.id, 'test-channel', 'Test Channel').then(({channel}) => {
testChannel = channel;
originalTestChannel = {...channel};
cy.apiAddUserToChannel(channel.id, user.id);
});
cy.apiLogin(testUser);
});
});
beforeEach(() => {
// Visit the channel before each test
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
});
// 2DO: update tests ids once QA has defined the test plan and zephyr tests
it('MM-T1: Can open and close the channel settings modal', () => {
// # Open channel settings modal from channel header dropdown
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// * Verify modal is open
cy.get('.ChannelSettingsModal').should('be.visible');
cy.get('#genericModalLabel').should('contain', 'Channel Settings');
// # Close the modal
cy.get('.GenericModal .modal-header button[aria-label="Close"]').click();
// * Verify modal is closed
cy.get('.ChannelSettingsModal').should('not.exist');
});
it('MM-T2: Can navigate between tabs', () => {
// # Open channel settings modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// * Verify Info tab is active by default
cy.get('#infoButton').should('have.class', 'active');
cy.get('.ChannelSettingsModal__infoTab').should('be.visible');
// # Click on Archive tab
cy.get('#archiveButton').click();
// * Verify Archive tab is active
cy.get('#archiveButton').should('have.class', 'active');
cy.get('.ChannelSettingsModal__archiveTab').should('be.visible');
// # Click back on Info tab
cy.get('#infoButton').click();
// * Verify Info tab is active again
cy.get('#infoButton').should('have.class', 'active');
cy.get('.ChannelSettingsModal__infoTab').should('be.visible');
});
it('MM-T3: Can edit channel name and URL', () => {
// # Open channel settings modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// # Get original channel name, url and alias it
cy.get('#input_channel-settings-name').invoke('val').as('originalName');
cy.get('.url-input-label').invoke('val').as('originalUrl');
// # Edit channel name
cy.get('#input_channel-settings-name').clear().type('Updated Channel Name');
// * Verify URL is updated automatically
cy.get('.url-input-label').should('contain', 'updated-channel-name');
// # Click Save
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();
// * Verify channel header shows updated name
cy.get('#channelHeaderTitle').should('contain', 'Updated Channel Name');
// # Open channel settings modal to restore original values
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// * Verify the channel name is reset to the original value
cy.get('#input_channel-settings-name').clear().type(originalTestChannel.display_name);
// # Try to change URL to match the original url
cy.get('.url-input-button').click();
cy.get('.url-input-container input').clear().type(originalTestChannel.name);
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();
// * Verify channel header shows updated name
cy.get('#channelHeaderTitle').should('contain', originalTestChannel.display_name);
});
it('MM-T4: Shows error for invalid channel name', () => {
// # Open channel settings modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// # Set empty channel name
cy.get('#input_channel-settings-name').clear();
// # Try Save changes
cy.get('[data-testid="SaveChangesPanel__save-btn"]').click();
// * Verify error is shown
cy.get('.Input_fieldset').should('have.class', 'Input_fieldset___error');
cy.get('.SaveChangesPanel').should('contain', 'There are errors in the form above');
});
it('MM-T6: Can edit channel purpose and header', () => {
// # Open channel settings modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// # Edit channel purpose
cy.get('#channel_settings_purpose_textbox').clear().type('This is a test purpose');
// # Edit channel header
cy.get('#channel_settings_header_textbox').clear().type('This is a test header');
// # 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();
// * Verify channel header shows updated header
cy.get('#channelHeaderDescription').should('contain', 'This is a test header');
});
it('MM-T7: Shows error when purpose exceeds character limit', () => {
// # Open channel settings modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// # Enter purpose that exceeds character limit (250 characters)
const longPurpose = 'a'.repeat(260);
cy.get('#channel_settings_purpose_textbox').clear().type(longPurpose);
// * Verify error is shown
cy.findAllByTestId('channel_settings_purpose_textbox').should('have.class', 'textarea--has-errors');
cy.get('.SaveChangesPanel').should('contain', 'There are errors in the form above');
});
it('MM-T8: Shows error when header exceeds character limit', () => {
// # Open channel settings modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// # Enter header that exceeds character limit (1024 characters)
const longHeader = 'a'.repeat(1050);
cy.findByTestId('channel_settings_header_textbox').clear().type(longHeader);
// * Verify error is shown
cy.findByTestId('channel_settings_header_textbox').should('have.class', 'textarea--has-errors');
cy.get('.SaveChangesPanel').should('contain', 'There are errors in the form above');
});
it('MM-T9: Can archive a channel and redirect to previous visited channel', () => {
// # Create a new channel for this test
cy.apiCreateChannel(testTeam.id, 'first-channel', 'First Channel').then(({channel: channel1}) => {
cy.apiCreateChannel(testTeam.id, 'second-channel', 'Second Channel').then(({channel}) => {
// # visit town square
cy.visit(`/${testTeam.name}/channels/${channel1.name}`);
// # visit just created channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Open channel settings modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// # Click on Archive tab
cy.get('#archiveButton').click();
// # Click Archive button
cy.get('#channelSettingsArchiveChannelButton').click();
// * Verify confirmation modal appears
cy.get('#archiveChannelConfirmModal').should('be.visible');
// # Confirm archive
cy.findByRole('button', {name: 'Confirm'}).click();
// * Verify redirect to Town Square
cy.url().should('include', channel1.name);
// * Verify channel is no longer in sidebar
cy.get('.SidebarChannel').contains('Archive Test').should('not.exist');
});
});
});
it('MM-T10: Warns when switching tabs with unsaved changes', () => {
// # Create a new channel for this test
cy.apiCreateChannel(testTeam.id, 'unsaved-test', 'Unsaved Test').then(({channel}) => {
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Open channel settings modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// # Make a change to the channel name
cy.get('#input_channel-settings-name').clear().type('Changed Name');
// # Try to switch to Archive tab
cy.get('#archiveButton').click();
// * Verify we're still on the Info tab due to unsaved changes
cy.get('#infoButton').should('have.class', 'active');
// * Verify save changes panel shows error
cy.get('.SaveChangesPanel').should('have.class', 'error');
});
});
// MM-T11: Can reset changes without saving
it('MM-T11: Can reset changes without saving', () => {
// # Create a new channel for this test
cy.apiCreateChannel(testTeam.id, 'reset-test', 'Reset Test').then(({channel}) => {
// # Visit the channel page using the channel name returned from the API
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Open channel settings modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// # Get original channel name and alias it
cy.get('#input_channel-settings-name').invoke('val').as('originalName');
// # Change the channel name
cy.get('#input_channel-settings-name').clear().type('Temporary Name');
// # Click the Reset button in the SaveChangesPanel
cy.get('.SaveChangesPanel button').contains('Reset').click();
// * Verify the channel name is reset to the original value
cy.get('@originalName').then((originalName) => {
cy.get('#input_channel-settings-name').should('have.value', originalName);
});
// * Verify the SaveChangesPanel is no longer visible
cy.get('.SaveChangesPanel').should('not.exist');
});
});
// MM-T12: Can preview purpose and header with markdown
it('MM-T12: Can preview purpose and header with markdown', () => {
// # Create a new channel for this test
cy.apiCreateChannel(testTeam.id, 'markdown-test', 'Markdown Test').then(({channel}) => {
// # Visit the channel page using the channel name returned from the API
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Open channel settings modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// # Add markdown to purpose
cy.get('#channel_settings_purpose_textbox').clear().type('This is **bold** and _italic_ text');
// # Click preview button for purpose (assumes preview button is inside the AdvancedTextbox container)
cy.get('#channel_settings_purpose_textbox').
parents('.AdvancedTextbox').
find('#PreviewInputTextButton').
click();
// * Verify that markdown is rendered in preview: check for bold and italic formatting
cy.get('.textbox-preview-area').
should('contain', 'This is').
find('strong').
should('contain', 'bold');
cy.get('.textbox-preview-area').
find('em').
should('contain', 'italic');
// # Add markdown to header
cy.get('#channel_settings_header_textbox').clear().type('Visit [Mattermost](https://mattermost.com)');
// # Click preview button for header
cy.get('#channel_settings_header_textbox').
parents('.AdvancedTextbox').
find('#PreviewInputTextButton').
click();
// * Verify that markdown is rendered in preview: check for a link with text "Mattermost"
cy.get('.textbox-preview-area').
should('contain', 'Visit').
find('a').
should('contain', 'Mattermost');
});
});
it('MM-T13: Validates URL when editing channel name', () => {
// # Create two channels to test URL conflict error
cy.apiCreateChannel(testTeam.id, 'first-channel', 'First Channel').then(({channel: channel1}) => {
cy.apiCreateChannel(testTeam.id, 'second-channel', 'Second Channel').then(({channel}) => {
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Open channel settings modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// # Try to change URL to match the first channel
cy.get('.url-input-button').click();
cy.get('.url-input-container input').clear().type(channel1.name);
cy.get('.url-input-container button.url-input-button').click();
// * Verify error is shown
cy.get('[data-testid="SaveChangesPanel__save-btn"]').click();
cy.get('.SaveChangesPanel').should('contain', 'There are errors in the form above');
});
});
});
});

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

@@ -37,22 +37,23 @@ describe('Channel Settings', () => {
// # Go to test channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Go to channel dropdown > Rename channel
cy.get('#channelHeaderTitle').click();
cy.findByText('Channel Settings').should('be.visible').trigger('mouseover');
cy.findByText('Rename Channel').click();
// # Go to channel dropdown > Channel Settings Modal
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// # Try to enter existing URL and save
cy.get('#channel_name').clear().type('town-square');
cy.get('#save-button').click();
cy.get('#input_channel-settings-name').clear().type('town-square');
cy.get('[data-testid="SaveChangesPanel__save-btn"]').click();
// # Error is displayed and URL is unchanged
cy.get('.has-error').should('be.visible').and('contain', 'A channel with that name already exists on the same team.');
cy.get('.SaveChangesPanel').should('contain', 'There are errors in the form above');
cy.get('.url-input-error').should('be.visible').and('contain.text', 'A channel with that name already exists on the same team.');
cy.url().should('include', `/${testTeam.name}/channels/${channel.name}`);
// # Enter a new URL and save
cy.get('#channel_name').clear().type('another-town-square');
cy.get('#save-button').click();
cy.get('#input_channel-settings-name').clear().type('another-town-square');
cy.get('[data-testid="SaveChangesPanel__save-btn"]').click();
// * URL is updated and no errors are displayed
cy.url().should('include', `/${testTeam.name}/channels/another-town-square`);

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

@@ -1,179 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Team} from '@mattermost/types/teams';
import {UserProfile} from '@mattermost/types/users';
// ***************************************************************
// - [#] 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
describe('Channels', () => {
let testUser: UserProfile;
let testTeam: Team;
before(() => {
cy.apiInitSetup().then(({team, user}) => {
testUser = user;
testTeam = team;
});
});
it('MM-T3348 - Convert to private channel should only be shown to users with permission', () => {
// # Reset permissions to default
resetPermissionsToDefault();
// # Enable convert public channels to private for all users
enablePermission('all_users-public_channel-convert_public_channel_to_private-checkbox');
saveConfig();
// # Login as a regular user
cy.apiLogin(testUser);
// # Create new test channel
cy.apiCreateChannel(testTeam.id, 'channel-test', 'Channel').then(({channel}) => {
// # Go to test channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Click the channel header dropdown
cy.get('#channelHeaderTitle').click();
// open ChannelSettings submenu
cy.findByRole('menuitem', {name: 'Channel Settings'}).trigger('mouseover');
// * Channel convert to private should be visible and confirm
cy.get('#channelConvertToPrivate').should('be.visible').click();
cy.findByTestId('convertChannelConfirm').should('be.visible').click();
// # Click the channel header dropdown
cy.get('#channelHeaderTitle').click();
// open ChannelSettings submenu
cy.findByRole('menuitem', {name: 'Channel Settings'}).trigger('mouseover');
// * Channel convert to private should no longer be visible
cy.get('#channelConvertToPrivate').should('not.exist');
});
// # Reset permissions to default
resetPermissionsToDefault();
// # Login as a regular user
cy.apiLogin(testUser);
// # Create new test channel
cy.apiCreateChannel(testTeam.id, 'channel-test', 'Channel').then(({channel}) => {
// # Go to test channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Click the channel header dropdown
cy.get('#channelHeaderTitle').click();
// open ChannelSettings submenu
cy.findByRole('menuitem', {name: 'Channel Settings'}).trigger('mouseover');
// * Channel convert to private should no longer be visible
cy.get('#channelConvertToPrivate').should('not.exist');
});
// # Reset permissions to default
resetPermissionsToDefault();
// # Remove permission from team admins
removePermission('team_admin-public_channel-convert_public_channel_to_private-checkbox');
saveConfig();
// # Promote user to team admin
cy.apiUpdateTeamMemberSchemeRole(testTeam.id, testUser.id, {scheme_admin: true, scheme_user: true});
// # Login as the now team admin user
cy.apiLogin(testUser);
// # Create new test channel
cy.apiCreateChannel(testTeam.id, 'channel-test', 'Channel').then(({channel}) => {
// # Go to test channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Click the channel header dropdown
cy.get('#channelHeaderTitle').click();
// open ChannelSettings submenu
cy.findByRole('menuitem', {name: 'Channel Settings'}).trigger('mouseover');
// * Channel convert to private should not be visible
cy.get('#channelConvertToPrivate').should('not.exist');
});
// # Reset permissions to default
resetPermissionsToDefault();
// # Login as the team admin user
cy.apiLogin(testUser);
// # Create new test channel
cy.apiCreateChannel(testTeam.id, 'channel-test', 'Channel').then(({channel}) => {
// # Go to test channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Click the channel header dropdown
cy.get('#channelHeaderTitle').click();
// open ChannelSettings submenu
cy.findByRole('menuitem', {name: 'Channel Settings'}).trigger('mouseover');
// * Channel convert to private should be visible and confirm
cy.get('#channelConvertToPrivate').should('be.visible').click();
cy.findByTestId('convertChannelConfirm').should('be.visible').click();
// # Click the channel header dropdown
cy.get('#channelHeaderTitle').click();
// open ChannelSettings submenu
cy.findByRole('menuitem', {name: 'Channel Settings'}).trigger('mouseover');
// * Channel convert to private should no longer be visible
cy.get('#channelConvertToPrivate').should('not.exist');
});
});
});
const saveConfig = () => {
cy.get('#saveSetting').click();
cy.waitUntil(() => cy.get('#saveSetting').then((el) => {
return el[0].innerText === 'Save';
}));
};
const enablePermission = (permissionCheckBoxTestId) => {
cy.findByTestId(permissionCheckBoxTestId).then((el) => {
if (!el.hasClass('checked')) {
el.click();
}
});
};
const removePermission = (permissionCheckBoxTestId) => {
cy.findByTestId(permissionCheckBoxTestId).then((el) => {
if (el.hasClass('checked')) {
el.click();
}
});
};
const resetPermissionsToDefault = () => {
// # Login as sysadmin and navigate to system scheme page
cy.apiAdminLogin();
cy.visit('/admin_console/user_management/permissions/system_scheme');
// # Click reset to defaults and confirm
cy.findByTestId('resetPermissionsToDefault').click();
cy.get('#confirmModalButton').click();
// # Save
saveConfig();
};

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

@@ -0,0 +1,567 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Team} from '@mattermost/types/teams';
import {UserProfile} from '@mattermost/types/users';
import {Channel} from '@mattermost/types/channels';
import {getAdminAccount} from '../../../support/env';
// ***************************************************************
// - [#] 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
describe('Channel Type Conversion (Public to Private Only)', () => {
let testUser: UserProfile;
let testTeam: Team;
const admin = getAdminAccount();
// Helper functions for permission management
const saveConfig = () => {
cy.waitUntil(() =>
cy.get('#saveSetting').then((button) => {
// Check if the button text is exactly "Save"
if (button.text().trim() === 'Save') {
button.click();
return true; // signals waitUntil that it succeeded
}
return false;
}),
);
};
const enablePermission = (permissionCheckBoxTestId: string) => {
cy.findByTestId(permissionCheckBoxTestId).then((el) => {
if (!el.hasClass('checked')) {
el.click();
}
});
};
const removePermission = (permissionCheckBoxTestId: string) => {
cy.findByTestId(permissionCheckBoxTestId).then((el) => {
if (el.hasClass('checked')) {
el.click();
}
});
};
const promoteToChannelAdmin = (userId, channelId, admin) => {
cy.externalRequest({
user: admin,
method: 'put',
path: `channels/${channelId}/members/${userId}/schemeRoles`,
data: {
scheme_user: true,
scheme_admin: true,
},
});
};
const resetPermissionsToDefault = () => {
// # Login as sysadmin and navigate to system scheme page
cy.apiAdminLogin();
cy.visit('/admin_console/user_management/permissions/system_scheme');
// # Click reset to defaults and confirm
cy.findByTestId('resetPermissionsToDefault').click();
cy.get('#confirmModalButton').click();
// # Save
saveConfig();
cy.wait(1000);
cy.visit('/admin_console/user_management/permissions/system_scheme');
};
// Helper functions for permission setup
const setupPermissions = (config: {
resetToDefault?: boolean;
publicToPrivate?: boolean;
removeFromTeamAdmin?: boolean;
}) => {
if (config.resetToDefault) {
resetPermissionsToDefault();
}
// Public to private conversion permissions
if (config.publicToPrivate) {
enablePermission('all_users-public_channel-convert_public_channel_to_private-checkbox');
} else if (config.publicToPrivate === false) {
removePermission('all_users-public_channel-convert_public_channel_to_private-checkbox');
}
// Remove public to private conversion from team admin if specified
if (config.removeFromTeamAdmin) {
removePermission('team_admin-public_channel-convert_public_channel_to_private-checkbox');
}
cy.wait(1000);
saveConfig();
};
// Helper functions for channel management
const createAndVisitPublicChannel = (teamName: string, channelId: string, displayName: string): Cypress.Chainable<Channel> => {
return cy.apiCreateChannel(testTeam.id, channelId, displayName).then(({channel}) => {
cy.apiAddUserToChannel(channel.id, testUser.id);
cy.visit(`/${teamName}/channels/${channel.name}`);
return cy.wrap(channel);
});
};
const createAndVisitPrivateChannel = (teamName: string, channelId: string, displayName: string): Cypress.Chainable<Channel> => {
return cy.apiCreateChannel(testTeam.id, channelId, displayName, 'P').then(({channel}) => {
cy.apiAddUserToChannel(channel.id, testUser.id);
cy.visit(`/${teamName}/channels/${channel.name}`);
return cy.wrap(channel);
});
};
const visitChannel = (teamName: string, channelName: string) => {
cy.visit(`/${teamName}/channels/${channelName}`);
};
// Helper functions for UI interaction
const openChannelSettingsModal = () => {
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
cy.get('.ChannelSettingsModal').should('be.visible');
};
const closeChannelSettingsModal = () => {
cy.get('.GenericModal .modal-header button[aria-label="Close"]').click();
cy.get('.ChannelSettingsModal').should('not.exist');
};
// Helper functions for UI interaction
const saveChannelSettings = () => {
cy.get('[data-testid="SaveChangesPanel__save-btn"]').click();
};
const verifySettingsSaved = () => {
cy.get('.SaveChangesPanel').should('contain', 'Settings saved');
};
// Helper functions for channel conversion
const convertChannelToPrivate = () => {
// Select private channel type
cy.get('#public-private-selector-button-P').click();
cy.get('#public-private-selector-button-P').should('have.class', 'selected');
// Save changes - this will trigger the confirmation modal
saveChannelSettings();
// Handle the confirmation modal that appears when converting from public to private
cy.get('#confirmModal').should('be.visible');
cy.get('#confirmModalButton').click();
// Verify settings were saved
verifySettingsSaved();
};
// Function kept for potential future use but not used in current tests
// since private to public conversion is no longer allowed
// const convertChannelToPublic = () => {
// cy.get('#public-private-selector-button-O').click();
// cy.get('#public-private-selector-button-O').should('have.class', 'selected');
// };
// Helper functions for verification
const verifyChannelIsPrivate = (channelName: string) => {
cy.get('.SidebarChannel').contains(channelName).parent().find('.icon-lock-outline').should('exist');
};
// Function kept for potential future use but not used in current tests
// since private to public conversion is no longer allowed
// const verifyChannelIsPublic = (channelName: string) => {
// cy.get('.SidebarChannel').contains(channelName).parent().find('.icon-lock-outline').should('not.exist');
// };
const verifyConversionOptionDisabled = (toPrivate = true) => {
if (toPrivate) {
// Wait for the UI to fully load and stabilize
cy.wait(500);
// Check if the button is disabled - it might have a disabled attribute or a disabled class
cy.get('#public-private-selector-button-P').then(($el) => {
const isDisabled = $el.hasClass('disabled') || $el.prop('disabled') === true || $el.attr('aria-disabled') === 'true';
expect(isDisabled).to.be.true;
});
} else {
// Wait for the UI to fully load and stabilize
cy.wait(500);
// Check if the button is disabled - it might have a disabled attribute or a disabled class
cy.get('#public-private-selector-button-O').then(($el) => {
const isDisabled = $el.hasClass('disabled') || $el.prop('disabled') === true || $el.attr('aria-disabled') === 'true';
expect(isDisabled).to.be.true;
});
}
};
const verifyConversionOptionEnabled = (toPrivate = true) => {
if (toPrivate) {
// Wait for the UI to fully load and stabilize
cy.wait(500);
// Check if the button is enabled - it should not have disabled attributes or classes
cy.get('#public-private-selector-button-P').then(($el) => {
const isDisabled = $el.hasClass('disabled') || $el.prop('disabled') === true || $el.attr('aria-disabled') === 'true';
expect(isDisabled).to.be.false;
});
} else {
// Wait for the UI to fully load and stabilize
cy.wait(500);
// Check if the button is enabled - it should not have disabled attributes or classes
cy.get('#public-private-selector-button-O').then(($el) => {
const isDisabled = $el.hasClass('disabled') || $el.prop('disabled') === true || $el.attr('aria-disabled') === 'true';
expect(isDisabled).to.be.false;
});
}
};
// Helper function to make user a channel admin
const makeUserChannelAdmin = (channelId: string, userId: string) => {
cy.apiAddUserToChannel(channelId, userId);
promoteToChannelAdmin(userId, channelId, admin);
};
// Helper function to make user a team admin
const makeUserTeamAdmin = (teamId: string, userId: string) => {
cy.apiUpdateTeamMemberSchemeRole(teamId, userId, {scheme_admin: true, scheme_user: true});
};
before(() => {
cy.apiInitSetup().then(({team, user}) => {
testUser = user;
testTeam = team;
});
});
beforeEach(() => {
// Reset to a clean state before each test
cy.apiLogin(testUser);
});
describe('Basic Conversion Functionality', () => {
it('MM-T3348-1 - Can convert a public channel to private', () => {
// # Setup permissions
setupPermissions({resetToDefault: true, publicToPrivate: true});
// # Create and visit a public channel
createAndVisitPublicChannel(testTeam.name, 'public-to-private', 'Public To Private').then((channel) => {
// # Open channel settings modal
openChannelSettingsModal();
// # Convert to private
convertChannelToPrivate();
// # Close the modal
closeChannelSettingsModal();
// * Verify channel is now private
verifyChannelIsPrivate(channel.display_name);
});
});
it('MM-T3348-5 - Cannot convert a private channel back to public', () => {
// # Setup permissions
setupPermissions({resetToDefault: true, publicToPrivate: true});
// # Create and visit a public channel
createAndVisitPublicChannel(testTeam.name, 'private-stays-private', 'Private Stays Private').then((channel) => {
// # Open channel settings modal
openChannelSettingsModal();
// # Convert to private
convertChannelToPrivate();
// # Close the modal
closeChannelSettingsModal();
// * Verify channel is now private
verifyChannelIsPrivate(channel.display_name);
// # Open channel settings modal again
openChannelSettingsModal();
// * Verify conversion option to public is disabled
verifyConversionOptionDisabled(false);
// # Close the modal
closeChannelSettingsModal();
});
});
});
describe('Role-Based Channel Type Conversion', () => {
it('MM-T3350-1 - System admin cannot convert a private channel to public', () => {
// # Reset permissions to default
resetPermissionsToDefault();
// # Login as system admin
cy.apiAdminLogin();
// # Create and visit a private channel
createAndVisitPrivateChannel(testTeam.name, 'sysadmin-private-stays-private', 'SysAdmin Private Channel').then(() => {
// # Open channel settings modal
openChannelSettingsModal();
// * Verify conversion option to public is disabled
verifyConversionOptionDisabled(false);
// # Close the modal
closeChannelSettingsModal();
});
});
it('MM-T3350-2 - Channel admin cannot convert a private channel to public', () => {
// # Reset permissions to default
setupPermissions({resetToDefault: true});
// # Login as regular user
cy.apiLogin(testUser);
// # Create and visit a private channel
createAndVisitPrivateChannel(testTeam.name, 'channel-admin-private', 'Channel Admin Private').then((channel) => {
// # Make test user a channel admin
makeUserChannelAdmin(channel.id, testUser.id);
// # Visit the channel again after role change
visitChannel(testTeam.name, channel.name);
// # Open channel settings modal
openChannelSettingsModal();
// * Verify conversion option to public is disabled
verifyConversionOptionDisabled(false);
// # Close the modal
closeChannelSettingsModal();
});
});
it('MM-T3350-3 - Team admin cannot convert a private channel to public', () => {
// # Reset permissions to default
setupPermissions({resetToDefault: true});
// # Make test user a team admin
makeUserTeamAdmin(testTeam.id, testUser.id);
// # Login as team admin
cy.apiLogin(testUser);
// # Create and visit a private channel
createAndVisitPrivateChannel(testTeam.name, 'team-admin-private', 'Team Admin Private').then(() => {
// # Open channel settings modal
openChannelSettingsModal();
// * Verify conversion option to public is disabled
verifyConversionOptionDisabled(false);
// # Close the modal
closeChannelSettingsModal();
});
});
it('MM-T3350-4 - Regular user cannot convert a private channel to public', () => {
// # Reset permissions to default
resetPermissionsToDefault();
// # Create a new regular user specifically for this test
cy.apiCreateUser().then(({user: regularUser}) => {
// # Add user to the team
cy.apiAddUserToTeam(testTeam.id, regularUser.id);
// # Have admin create a private channel
cy.apiAdminLogin();
cy.apiCreateChannel(testTeam.id, 'admin-created-private', 'Admin Created Private', 'P').then(({channel}) => {
// # Add the regular user to the channel (as a regular member, not admin)
cy.apiAddUserToChannel(channel.id, regularUser.id);
// # Login as the regular user
cy.apiLogin(regularUser);
// # Visit the channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Open channel settings modal
openChannelSettingsModal();
// * Verify conversion option is disabled
verifyConversionOptionDisabled(false);
// # Close the modal
closeChannelSettingsModal();
});
});
});
});
describe('Permission-Based Tests', () => {
it('MM-T3348-2 - Regular user without permission cannot convert public to private', () => {
// # Setup permissions - remove public to private conversion permission
setupPermissions({resetToDefault: true, publicToPrivate: false});
// # Create a new regular user specifically for this test
cy.apiCreateUser().then(({user: regularUser}) => {
// # Add user to the team
cy.apiAddUserToTeam(testTeam.id, regularUser.id);
// # Have admin create a public channel
cy.apiAdminLogin();
cy.apiCreateChannel(testTeam.id, 'admin-created-public', 'Admin Created Public').then(({channel}) => {
// # Add the regular user to the channel (as a regular member, not admin)
cy.apiAddUserToChannel(channel.id, regularUser.id);
// # Login as the regular user
cy.apiLogin(regularUser);
// # Visit the channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Open channel settings modal
openChannelSettingsModal();
// * Verify conversion option is disabled
verifyConversionOptionDisabled(true);
// # Close the modal
closeChannelSettingsModal();
});
});
});
it('MM-T3348-3 - Team admin can convert public to private by default', () => {
// # Setup permissions - reset to default
setupPermissions({resetToDefault: true});
// # Make test user a team admin
makeUserTeamAdmin(testTeam.id, testUser.id);
// # Create and visit a public channel
createAndVisitPublicChannel(testTeam.name, 'team-admin-convert', 'Team Admin Convert').then((channel) => {
// # Open channel settings modal
openChannelSettingsModal();
// * Verify conversion option is enabled
verifyConversionOptionEnabled(true);
// # Convert to private
convertChannelToPrivate();
// # Close the modal
closeChannelSettingsModal();
// * Verify channel is now private
verifyChannelIsPrivate(channel.display_name);
});
});
it('MM-T3348-4 - Team admin cannot convert when permission is removed', () => {
// # Setup permissions - remove permission from team admin
setupPermissions({
resetToDefault: true,
removeFromTeamAdmin: true,
});
// # Make test user a team admin
makeUserTeamAdmin(testTeam.id, testUser.id);
// # Have admin create a public channel
cy.apiAdminLogin();
cy.apiCreateChannel(testTeam.id, 'admin-created-team-admin-no-perm', 'Admin Created Team Admin No Permission').then(({channel}) => {
// # Add the team admin user to the channel (as a regular member, not channel admin)
cy.apiAddUserToChannel(channel.id, testUser.id);
// # Login as the team admin user
cy.apiLogin(testUser);
// # Visit the channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// # Open channel settings modal
openChannelSettingsModal();
// * Verify conversion option is disabled
verifyConversionOptionDisabled(true);
// # Close the modal
closeChannelSettingsModal();
});
});
});
describe('Channel Admin Tests', () => {
it('MM-T3349-1 - Channel admin can convert public to private when permission is enabled', () => {
// # Setup permissions - enable public to private conversion permission
setupPermissions({resetToDefault: true, publicToPrivate: true});
// # Create and visit a public channel
createAndVisitPublicChannel(testTeam.name, 'channel-admin-pub', 'Channel Admin Public').then((channel) => {
// # Make test user a channel admin
makeUserChannelAdmin(channel.id, testUser.id);
// # Visit the channel again after role change
visitChannel(testTeam.name, channel.name);
// # Open channel settings modal
openChannelSettingsModal();
// * Verify conversion option is enabled
verifyConversionOptionEnabled(true);
// # Convert to private
convertChannelToPrivate();
// # Close the modal
closeChannelSettingsModal();
// * Verify channel is now private
verifyChannelIsPrivate(channel.display_name);
});
});
it('MM-T3349-2 - Channel admin cannot convert public to private when permission is removed', () => {
// Generate a unique channel name with timestamp to avoid conflicts
const timestamp = Date.now();
const channelId = `channel-admin-no-perm-${timestamp}`;
const displayName = `Channel Admin No Permission ${timestamp}`;
// # Setup permissions - remove public to private conversion permission
setupPermissions({resetToDefault: true, publicToPrivate: false, removeFromTeamAdmin: true});
// # Create and visit a public channel
createAndVisitPublicChannel(testTeam.name, channelId, displayName).then((channel) => {
// # Make test user a channel admin
makeUserChannelAdmin(channel.id, testUser.id);
// # Log back in as the test user after making channel admin
cy.apiLogin(testUser);
// # Wait for login to complete
cy.wait(500);
// # Visit the channel again after role change
visitChannel(testTeam.name, channel.name);
// # Wait for channel to load
cy.wait(500);
// # Open channel settings modal
openChannelSettingsModal();
// * Verify conversion option is disabled
verifyConversionOptionDisabled(true);
// # Close the modal
closeChannelSettingsModal();
});
});
});
});

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

@@ -58,19 +58,7 @@ describe('Leave and Archive channel actions display as destructive', () => {
cy.get('#channelMembers').should('be.visible');
// * Channel Settings menu option should be visible
cy.findByText('Channel Settings').should('be.visible').trigger('mouseover');
// * Edit Channel Header menu option should be visible
cy.get('#channelEditHeader').should('be.visible');
// * Edit Channel Purpose menu option should be visible
cy.get('#channelEditPurpose').should('be.visible');
// * Rename Channel menu option should be visible
cy.get('#channelRename').should('be.visible');
// * Channel Settings close menu option
cy.findByText('Channel Settings').should('be.visible').trigger('mouseout');
cy.findByText('Channel Settings').should('be.visible');
// * Archive Channel menu option should be visible and have a background-color (destructive)
cy.get('#channelArchiveChannel').should('be.visible').focus().should('have.css', 'background-color', 'rgb(210, 75, 78)');

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

@@ -14,15 +14,13 @@ import * as TIMEOUTS from '../../../fixtures/timeouts';
import {getRandomId} from '../../../utils';
describe('Channel routing', () => {
let testTeam: Cypress.Team;
let testUser: Cypress.UserProfile;
let testChannel: Cypress.Channel;
let testTeam: any;
let testUser: any;
before(() => {
cy.apiInitSetup().then(({team, user, channel}) => {
cy.apiInitSetup().then(({team, user}) => {
testTeam = team;
testUser = user;
testChannel = channel;
// # Login as test user and go to town square
cy.apiLogin(testUser);
@@ -34,24 +32,25 @@ describe('Channel routing', () => {
// # Create new test channel
cy.uiCreateChannel({name: 'Test__Channel'});
// # Click on channel menu and press rename channel
cy.get('#channelHeaderTitle').click();
// # Open channel settings modal from channel header dropdown
cy.get('#channelHeaderDropdownButton').click();
cy.findByText('Channel Settings').click();
// * Channel Settings menu option should be visible
cy.findByText('Channel Settings').should('be.visible').trigger('mouseover');
cy.findByText('Rename Channel').click();
// # Assert if the channel settings modal is present
cy.get('.ChannelSettingsModal').should('be.visible');
// # Assert if the rename modal present
cy.get('[aria-labelledby="renameChannelModalLabel"').should('be.visible').within(() => {
// # type the two 26 character strings with 2 underscores between them and click on save
cy.get('#channel_name').clear().type('uzsfmtmniifsjgesce4u7yznyh__uzsfmtmniifsjgesce5u7yznyh', {force: true}).wait(TIMEOUTS.HALF_SEC);
cy.get('#save-button').should('be.visible').click();
// # Click on the URL input button to edit the URL
cy.get('.url-input-button').should('be.visible').click({force: true});
// # Assert the error occurred with the appropriate message
cy.get('.input__help').should('have.class', 'error');
cy.get('.input__help').should('have.text', 'User IDs are not allowed in channel URLs.');
cy.findByText('Cancel').click();
});
// # 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.');
// # 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', () => {
@@ -97,42 +96,34 @@ describe('Channel routing', () => {
it('MM-T883 Channel URL validation for spaces between characters', () => {
const firstWord = getRandomId(26);
const secondWord = getRandomId(26);
const channelName = 'test-channel-' + getRandomId(8);
// # In a test channel, click the "v" to the right of the channel name in the header
cy.findByText(`${testChannel.display_name}`).click();
cy.get('#channelHeaderTitle').click();
// # 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}`);
});
// * Channel Settings menu option should be visible
cy.findByText('Channel Settings').should('be.visible').trigger('mouseover');
// # Select "Rename Channel"
cy.findByText('Rename Channel').click();
// # 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('#display_name').clear().type(`${firstWord}${Cypress._.repeat(' ', 2)}${secondWord}`);
cy.get('#input_channel-settings-name').clear().type(`${firstWord}${Cypress._.repeat(' ', 2)}${secondWord}`);
// # Hit Save
cy.findByText('Save').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}`);
// # In a test channel, click the "v" to the right of the channel name in the header
cy.get('#channelHeaderTitle').click();
// * Channel Settings menu option should be visible
cy.findByText('Channel Settings').should('be.visible').trigger('mouseover');
// # Select "Rename Channel"
cy.findByText('Rename Channel').click();
// # Change the URL to {26 alphanumeric characters}--{26 alphanumeric characters}
cy.get('#channel_name').clear().type(`${firstWord}${Cypress._.repeat('-', 2)}${secondWord}`);
// # Hit Save
cy.findByText('Save').click();
// * 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}`);
});

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

@@ -202,22 +202,33 @@ describe('Team Permissions', () => {
// # Visit the `Off-Topic` channel in the new team
cy.visit(`/${team.name}/channels/off-topic`);
// # Open channel header menu
cy.uiOpenChannelMenu().wait(TIMEOUTS.HALF_SEC);
// # Open channel header dropdown
cy.get('#channelHeaderDropdownButton').click();
// * Verify dropdown opens
cy.get('#channelHeaderDropdownMenu').should('be.visible');
cy.findByText('Channel Settings').should('be.visible').trigger('mouseover');
// * Verify Channel Settings option is visible
cy.findByText('Channel Settings').should('be.visible');
// * Verify `Edit Channel Header` menu item is visible
cy.get('#channelEditHeader').should('be.visible');
// # Click on Channel Settings
cy.findByText('Channel Settings').click();
// * Verify `Edit Channel Purpose` menu item is visible
cy.get('#channelEditPurpose').should('be.visible');
// * Verify Channel Settings modal opens
cy.get('.ChannelSettingsModal').should('be.visible');
// * Verify `Rename Channel` menu item is visible
cy.get('#channelRename').should('be.visible');
// * Verify user can edit channel name
cy.get('#input_channel-settings-name').should('be.visible').and('not.be.disabled');
// * Verify user can edit channel URL
cy.get('.url-input-button').should('be.visible').and('not.be.disabled');
// * Verify user can edit channel purpose
cy.get('#channel_settings_purpose_textbox').should('be.visible').and('not.be.disabled');
// * Verify user can edit channel header
cy.get('#channel_settings_header_textbox').should('be.visible').and('not.be.disabled');
// # Close the modal
cy.get('.GenericModal .modal-header button[aria-label="Close"]').click();
cy.get('.ChannelSettingsModal').should('not.exist');
});
});
});

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

@@ -114,13 +114,15 @@ describe('Keyboard shortcut CTRL/CMD+Shift+\\ for adding reaction to last messag
cy.uiOpenProfileModal('Profile Settings');
verifyEmojiPickerNotOpen();
['Edit Channel Header', 'Rename Channel'].forEach((modal) => {
// # Click on the channel name in the channel header to open the channel menu options
cy.get('#channelHeaderTitle').click();
// # Open Channel Settings Modal
cy.uiOpenChannelMenu('Channel Settings');
verifyEmojiPickerNotOpen();
// # Select the "Edit Channel Header" option from the dropdown
cy.findByText('Channel Settings').should('be.visible').trigger('mouseover');
cy.findByText(modal).click();
['Channel Purpose', 'Channel Header'].forEach((modal) => {
// # Open channel menu and click View Info
cy.uiOpenChannelMenu('View Info');
cy.findByText(modal).parent().findAllByRole('button', {name: 'Edit'}).click();
doReactToLastMessageShortcut();
@@ -129,6 +131,9 @@ describe('Keyboard shortcut CTRL/CMD+Shift+\\ for adding reaction to last messag
// # Close the modal
pressEscapeKey();
// # Close channel info
cy.uiOpenChannelMenu('Close Info');
});
});

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

@@ -53,7 +53,7 @@ describe('Onboarding', () => {
// # Enable any user with an account on the server to join the team
cy.get('input.mm-modal-generic-section-item__input-checkbox').last().should('be.visible').click();
cy.findAllByTestId('mm-save-changes-panel__save-btn').should('be.visible').click();
cy.get('[data-testid="SaveChangesPanel__save-btn"]').should('be.visible').click();
// # Close the modal
cy.findByLabelText('Close').should('be.visible').click();

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

@@ -102,11 +102,19 @@ describe('channels > run', {testIsolation: true}, () => {
cy.startPlaybookRunWithSlashCommand('Playbook', playbookRunName);
cy.verifyPlaybookRunActive(testTeam.id, playbookRunName);
// # Open the channel header
cy.get('#channelHeaderTitle').click();
cy.findByText('Channel Settings').should('be.visible').trigger('mouseover');
// # Open channel header dropdown
cy.get('#channelHeaderDropdownButton').click();
// # Click on Channel Settings
cy.findByText('Channel Settings').should('be.visible').click();
// * Verify Channel Settings modal opens
cy.get('.ChannelSettingsModal').should('be.visible');
// * Verify the ability to edit the channel header exists
cy.get('#channelEditHeader').should('exist');
cy.get('#channel_settings_header_textbox').should('be.visible').and('not.be.disabled');
// # Close the modal
cy.get('.GenericModal .modal-header button[aria-label="Close"]').click();
});
});