diff --git a/e2e-tests/cypress/tests/integration/channels/channel/channel_settings_modal_spec.ts b/e2e-tests/cypress/tests/integration/channels/channel/channel_settings_modal_spec.ts index 1c8340c4a8..8f3d3cbb20 100644 --- a/e2e-tests/cypress/tests/integration/channels/channel/channel_settings_modal_spec.ts +++ b/e2e-tests/cypress/tests/integration/channels/channel/channel_settings_modal_spec.ts @@ -95,8 +95,10 @@ describe('Channel Settings Modal', () => { // # 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'); + // * Verify URL remains unchanged (does not auto-update when editing existing channels) + cy.get('@originalUrl').then((originalUrl) => { + cy.get('.url-input-label').should('contain', originalUrl); + }); // # Click Save cy.get('[data-testid="SaveChangesPanel__save-btn"]').click(); @@ -135,6 +137,99 @@ describe('Channel Settings Modal', () => { cy.get('#channelHeaderTitle').should('contain', originalTestChannel.display_name); }); + it('MM-T31: Channel name changes do not auto-update URL, URL only changes when explicitly modified', () => { + // # Create a new channel for this test + cy.apiCreateChannel(testTeam.id, 'url-behavior-test', 'URL Behavior Test').then(({channel}) => { + cy.visit(`/${testTeam.name}/channels/${channel.name}`); + + // # Open channel settings modal + cy.get('#channelHeaderDropdownButton').click(); + cy.findByText('Channel Settings').click(); + + // # Store original values + cy.get('#input_channel-settings-name').invoke('val').as('originalName'); + cy.get('.url-input-label').invoke('val').as('originalUrl'); + + // # Verify changing channel name does NOT auto-update URL + + // # Change the channel name + cy.get('#input_channel-settings-name').clear().type('New Channel Name'); + + // * Verify URL remains unchanged after name change + cy.get('@originalUrl').then((originalUrl) => { + cy.get('.url-input-label').should('contain', originalUrl); + }); + + // # Save the name change + cy.get('[data-testid="SaveChangesPanel__save-btn"]').click(); + + // * Verify changes are saved + cy.get('.SaveChangesPanel').should('contain', 'Settings saved'); + + // * Verify URL is still the original URL after saving + cy.get('@originalUrl').then((originalUrl) => { + cy.get('.url-input-label').should('contain', originalUrl); + }); + + // # Verify URL only changes when explicitly modified + + // # Click the URL edit button to enable URL editing + cy.get('.url-input-button').click(); + + // # Modify the URL explicitly + cy.get('.url-input-container input').clear().type('explicitly-changed-url'); + + // # Confirm the URL change + cy.get('.url-input-container button.url-input-button').click(); + + // * Verify URL has been updated to the new value + cy.get('.url-input-label').should('contain', 'explicitly-changed-url'); + + // # Save the URL change + 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 the URL has actually changed by checking the browser URL + cy.url().should('include', 'explicitly-changed-url'); + + // # Verify subsequent name changes still don't affect the explicitly set URL + + // # Open channel settings modal again + cy.get('#channelHeaderDropdownButton').click(); + cy.findByText('Channel Settings').click(); + + // # Store the current URL (which should be the explicitly changed one) + cy.get('.url-input-label').invoke('val').as('currentUrl'); + + // # Change the channel name again + cy.get('#input_channel-settings-name').clear().type('Another Name Change'); + + // * Verify URL remains the explicitly set URL, not auto-generated from new name + cy.get('@currentUrl').then((currentUrl) => { + cy.get('.url-input-label').should('contain', currentUrl); + }); + + // * Verify URL does NOT contain auto-generated value from new name + cy.get('.url-input-label').should('not.contain', 'another-name-change'); + + // # Save the second name change + cy.get('[data-testid="SaveChangesPanel__save-btn"]').click(); + + // * Verify changes are saved + cy.get('.SaveChangesPanel').should('contain', 'Settings saved'); + + // * Final verification: URL should still be the explicitly set one + cy.get('@currentUrl').then((currentUrl) => { + cy.get('.url-input-label').should('contain', currentUrl); + }); + }); + }); + it('MM-T4: Shows error for invalid channel name', () => { // # Open channel settings modal cy.get('#channelHeaderDropdownButton').click(); diff --git a/e2e-tests/cypress/tests/integration/channels/channel/channel_settings_spec.ts b/e2e-tests/cypress/tests/integration/channels/channel/channel_settings_spec.ts index 961595e7fd..a5aba88c60 100644 --- a/e2e-tests/cypress/tests/integration/channels/channel/channel_settings_spec.ts +++ b/e2e-tests/cypress/tests/integration/channels/channel/channel_settings_spec.ts @@ -34,15 +34,22 @@ describe('Channel Settings', () => { it('MM-T882 Channel URL validation works properly', () => { cy.apiCreateChannel(testTeam.id, 'channel-test', 'Channel').then(({channel}) => { - // # Go to test channel + // # Go to test channel cy.visit(`/${testTeam.name}/channels/${channel.name}`); // # Go to channel dropdown > Channel Settings Modal cy.get('#channelHeaderDropdownButton').click(); cy.findByText('Channel Settings').click(); - // # Try to enter existing URL and save + // # Change channel name (this should NOT affect the URL anymore) cy.get('#input_channel-settings-name').clear().type('town-square'); + + // # Now explicitly change the URL to trigger the validation error + cy.get('.url-input-button').click(); + cy.get('.url-input-container input').clear().type('town-square'); + cy.get('.url-input-container button.url-input-button').click(); + + // # Try to save cy.get('[data-testid="SaveChangesPanel__save-btn"]').click(); // # Error is displayed and URL is unchanged @@ -52,7 +59,9 @@ describe('Channel Settings', () => { cy.url().should('include', `/${testTeam.name}/channels/${channel.name}`); // # Enter a new URL and save - cy.get('#input_channel-settings-name').clear().type('another-town-square'); + cy.get('.url-input-container input').clear().type('another-town-square'); + cy.get('.url-input-button').click(); + cy.get('.url-input-container button.url-input-button').click(); cy.get('[data-testid="SaveChangesPanel__save-btn"]').click(); // * URL is updated and no errors are displayed diff --git a/e2e-tests/cypress/tests/integration/channels/channel_settings/channel_name_validations_spec.ts b/e2e-tests/cypress/tests/integration/channels/channel_settings/channel_name_validations_spec.ts index dcb6b858b7..7d753872fc 100644 --- a/e2e-tests/cypress/tests/integration/channels/channel_settings/channel_name_validations_spec.ts +++ b/e2e-tests/cypress/tests/integration/channels/channel_settings/channel_name_validations_spec.ts @@ -112,6 +112,11 @@ describe('Channel routing', () => { // 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(); diff --git a/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx b/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx index 88aeff8c89..010af646d6 100644 --- a/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx +++ b/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx @@ -30,6 +30,7 @@ export type Props = { team?: Team; urlError?: string; readOnly?: boolean; + isEditingExistingChannel?: boolean; } import './channel_name_form_field.scss'; @@ -101,8 +102,8 @@ const ChannelNameFormField = (props: Props): JSX.Element => { displayName.current = updatedDisplayName; props.onDisplayNameChange(updatedDisplayName); - if (!urlModified.current) { - // if URL isn't explicitly modified, it's derived from the display name + if (!urlModified.current && !props.isEditingExistingChannel) { + // Only auto-generate URL for new channels, not when editing existing ones const cleanURL = cleanUpUrlable(updatedDisplayName); setURL(cleanURL); setURLError(''); diff --git a/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.test.tsx b/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.test.tsx index c0850e65ad..01248bd3bc 100644 --- a/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.test.tsx +++ b/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.test.tsx @@ -204,10 +204,11 @@ describe('ChannelSettingsInfoTab', () => { }); // Verify patchChannel was called with the updated values (without type change). + // Note: URL should remain unchanged when editing existing channels expect(patchChannel).toHaveBeenCalledWith('channel1', { ...mockChannel, display_name: 'Updated Channel Name', - name: 'updated-channel-name', + name: 'test-channel', // URL should remain unchanged when editing existing channels purpose: 'Updated purpose', header: 'Updated header', }); @@ -249,7 +250,7 @@ describe('ChannelSettingsInfoTab', () => { expect(patchChannel).toHaveBeenCalledWith('channel1', { ...mockChannel, display_name: 'Channel Name With Whitespace', // Whitespace should be trimmed - name: 'channel-name-with-whitespace', // URL is generated from display name and should be trimmed + name: 'test-channel', // URL should remain unchanged when editing existing channels purpose: 'Purpose with whitespace', // Whitespace should be trimmed header: 'Header with whitespace', // Whitespace should be trimmed }); diff --git a/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.tsx b/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.tsx index e894f7e2ef..4635b3c49c 100644 --- a/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.tsx +++ b/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.tsx @@ -364,6 +364,7 @@ function ChannelSettingsInfoTab({ urlError={internalUrlError} currentUrl={channelUrl} readOnly={!canManageChannelProperties} + isEditingExistingChannel={true} /> {/* Channel Type Section*/}