Files
1325e23fc6 MM-66561 Add distinct archive icon for private channels (#34736)
* MM-66561 Add distinct archive icon for private channels

Archived private channels now display an archive-lock icon instead of the standard archive icon to better indicate their original privacy level. Implemented utility functions to centralize icon selection logic across all channel list views, sidebars, headers, and suggestion providers.

* MM-66561 Fix linting and TypeScript errors

Fix ESLint and TypeScript issues introduced in the archive icon implementation:
- Remove extra blank lines to comply with no-multiple-empty-lines rule
- Remove unused container variables in test files
- Fix import order to comply with import/order rule
- Remove unused React import
- Fix TypeScript type errors by using General.OPEN_CHANNEL/PRIVATE_CHANNEL from mattermost-redux/constants which preserves literal types

* MM-66561 Fix test failures for archive icon changes

Update test snapshots and fix test data issues related to the new distinct archive icons for public and private channels.

- Update snapshots for channel list components to include new channelType prop and data-testid attributes
- Fix channel_mention_provider test by preserving actual module exports in mock
- Add missing purpose field to searchable_channel_list test data
- Fix async state handling in new_channel_modal test using waitFor instead of act

* MM-66561 Fix remaining Cypress E2E test failures for archive icons

Fix three failing Cypress tests related to archive icon changes:

1. join_archived_channel_spec.ts (MM-T1682, MM-T1683)
   - Add data-testid to archive icon in channel header
   - Update test to use findByTestId instead of CSS class selector
   - Compass icon components render as SVG, not <i> with classes

2. archived_channels_spec.js (system console tests)
   - Add "000-" prefix to private channel name/display name
   - Ensures proper alphabetical sorting on first page of results

3. long_draft_spec.js (MM-T211)
   - Fix Cypress alias timing issues in nested then() callbacks
   - Use local variable to track height changes during iteration
   - Replace cy.get('@alias').should() with direct expect() assertions

All tests now pass with the distinct archive icons for private channels.

* fix lint issue

* MM-66561 Refine archive icon styling and search results display

- Restore CSS classes on channel header icon for proper color and size
- Fix icon alignment by removing top offset in channel header context
- Replace "Archived" text with icon-only tooltip in search results
- Add context-specific styling to prevent conflicts between header and search

* tweaks to css and move withtooltip to wrap the span

* lint fix

* lint fix

* Fix archived channel icons visual test API usage

Update test to use correct Playwright API patterns:
- Use adminClient.createChannel with pw.random.channel for channel creation
- Use adminClient.deleteChannel instead of pw.apiClient.deleteChannel
- Use pw.testBrowser.login(adminUser) instead of loginAsAdmin
- Remove channelsPage.toBeVisible check for archived channels since they lack post-create element

* Apply prettier formatting to archived channel icons test

* Fix timing issue in MM-T633 Elasticsearch webhook attachment search test

The test was intermittently failing because it searched immediately after posting the webhook, before Elasticsearch had time to index the new post. Added explicit wait for post to appear and increased indexing wait time to 3 seconds to ensure the attachment text is indexed before performing the search.

---------

Co-authored-by: Matthew Birtch <[email protected]>

Co-authored-by: Hanzo Dev <[email protected]>
2026-01-14 15:35:27 +00:00

162 lines
5.8 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test} from '@mattermost/playwright-lib';
/**
* @objective Verify archived channel icons display correctly for public and private channels in various UI contexts
*/
test(
'displays archive icons for public and private channels in sidebar',
{tag: ['@visual', '@archived_channels', '@snapshots']},
async ({pw, browserName, viewport}, testInfo) => {
// # Initialize setup and create test channels
const {team, user, adminClient} = await pw.initSetup();
// # Create public and private channels
const publicChannel = await adminClient.createChannel(
pw.random.channel({
teamId: team.id,
name: 'public-to-archive',
displayName: 'Public Archive Test',
type: 'O',
}),
);
const privateChannel = await adminClient.createChannel(
pw.random.channel({
teamId: team.id,
name: 'private-to-archive',
displayName: 'Private Archive Test',
type: 'P',
}),
);
// # Archive both channels
await adminClient.deleteChannel(publicChannel.id);
await adminClient.deleteChannel(privateChannel.id);
// # Log in user
const {page, channelsPage} = await pw.testBrowser.login(user);
// # Visit town square to ensure we're in a stable state
await channelsPage.goto(team.name, 'town-square');
await channelsPage.toBeVisible();
// # Open browse channels modal to show archived channels
await page.keyboard.press('Control+K');
await page.waitForTimeout(500);
// # Type to search for archived channels
await page.keyboard.type('archive');
await page.waitForTimeout(500);
// # Hide dynamic content
await pw.hideDynamicChannelsContent(page);
// * Verify channel switcher shows both archived channels with correct icons
const testArgs = {page, browserName, viewport};
await pw.matchSnapshot(testInfo, testArgs);
},
);
/**
* @objective Verify archived channel icons display correctly in admin console channel list
*/
test(
'displays archive icons in admin console channel list',
{tag: ['@visual', '@archived_channels', '@admin_console', '@snapshots']},
async ({pw, browserName, viewport}, testInfo) => {
// # Initialize setup with admin user
const {team, adminUser, adminClient} = await pw.initSetup();
// # Create public and private channels
const publicChannel = await adminClient.createChannel(
pw.random.channel({
teamId: team.id,
name: 'admin-public-archive',
displayName: 'Admin Public Archive',
type: 'O',
}),
);
const privateChannel = await adminClient.createChannel(
pw.random.channel({
teamId: team.id,
name: 'admin-private-archive',
displayName: 'Admin Private Archive',
type: 'P',
}),
);
// # Archive both channels
await adminClient.deleteChannel(publicChannel.id);
await adminClient.deleteChannel(privateChannel.id);
// # Log in as admin
const {page} = await pw.testBrowser.login(adminUser);
// # Navigate to admin console channels list
await page.goto('/admin_console/user_management/channels');
await page.waitForTimeout(1000);
// # Wait for channel list to load
await expect(page.locator('.DataGrid')).toBeVisible({timeout: 10000});
// # Search for our test channels to bring them into view
await page.fill('[data-testid="searchInput"]', 'Admin');
await page.waitForTimeout(500);
// * Verify both archived channels are visible with correct icons
const testArgs = {page, browserName, viewport};
await pw.matchSnapshot(testInfo, testArgs);
},
);
/**
* @objective Verify archived private channel icon displays in channel header when viewing archived channel
*/
test(
'displays archive icon in channel header for archived private channel',
{tag: ['@visual', '@archived_channels', '@channel_header', '@snapshots']},
async ({pw, browserName, viewport}, testInfo) => {
// # Initialize setup
const {team, adminUser, adminClient} = await pw.initSetup();
// # Create a private channel
const privateChannel = await adminClient.createChannel(
pw.random.channel({
teamId: team.id,
name: 'private-header-test',
displayName: 'Private Header Test',
type: 'P',
}),
);
// # Archive the channel
await adminClient.deleteChannel(privateChannel.id);
const {page, channelsPage} = await pw.testBrowser.login(adminUser);
// # Visit the archived channel directly
await channelsPage.goto(team.name, privateChannel.name);
// # Wait for channel header to load (archived channels don't have post-create)
await expect(page.locator('.channel-header')).toBeVisible();
// # Verify archived channel message is visible
await expect(page.locator('#channelArchivedMessage')).toBeVisible();
// # Hide dynamic content
await pw.hideDynamicChannelsContent(page);
// # Focus on channel header area for snapshot
const headerElement = page.locator('.channel-header');
await expect(headerElement).toBeVisible();
// * Verify channel header shows archive-lock icon for private archived channel
const testArgs = {page, browserName, viewport};
await pw.matchSnapshot(testInfo, testArgs);
},
);