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,82 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import path from 'node:path';
import {expect, test} from '@mattermost/playwright-lib';
/**
* @objective Verify that on a licensed server the Bookmarks Bar option is available in the channel menu with
* an "Add a link" action, even when the channel has no bookmarks yet.
*
* MM-T5601 covers the same behavior as MM-T5600 and is covered by this test.
*/
test('MM-T5600 MM-T5601 shows the Bookmarks Bar option in the channel menu', {tag: '@channels'}, async ({pw}) => {
const {user, team} = await pw.initSetup();
const {channelsPage} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, 'town-square');
await channelsPage.toBeVisible();
// # Open the channel menu
const channelMenu = await channelsPage.openChannelMenu();
// * Verify the Bookmarks Bar option is available
await expect(channelMenu.bookmarksBar).toBeVisible();
// # Open the Bookmarks Bar submenu
await channelMenu.openBookmarksSubmenu();
// * Verify the "Add a link" action is available
await expect(channelMenu.addBookmarkLink).toBeVisible();
});
/**
* @objective Verify a user can add a link bookmark from the channel menu's Bookmarks Bar submenu and see it
* in the channel bookmarks bar.
*/
test('MM-T5602 adds a link bookmark to the channel bookmarks bar', {tag: '@channels'}, async ({pw}) => {
const {user, team} = await pw.initSetup();
const {channelsPage} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, 'town-square');
await channelsPage.toBeVisible();
// # Open the Bookmarks Bar submenu from the channel menu and choose "Add a link"
const channelMenu = await channelsPage.openChannelMenu();
await channelMenu.openBookmarksSubmenu();
await channelMenu.addBookmarkLink.click();
// # Enter a link and add the bookmark
await channelsPage.bookmarkCreateModal.toBeVisible();
await channelsPage.bookmarkCreateModal.addLink('https://www.mattermost.com');
// * Verify the bookmark appears in the channel bookmarks bar
await channelsPage.channelBookmarksBar.toBeVisible();
await expect(channelsPage.channelBookmarksBar.getBookmark(/mattermost/i)).toBeVisible();
});
/**
* @objective Verify a user can add a file bookmark from the channel menu's Bookmarks Bar submenu and see it
* in the channel bookmarks bar.
*/
test('MM-T5603 adds a file bookmark to the channel bookmarks bar', {tag: '@channels'}, async ({pw}) => {
const {user, team} = await pw.initSetup();
const {channelsPage, page} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, 'town-square');
await channelsPage.toBeVisible();
// # Open the Bookmarks Bar submenu and choose "Attach a file", selecting a file
const channelMenu = await channelsPage.openChannelMenu();
await channelMenu.openBookmarksSubmenu();
const fileChooserPromise = page.waitForEvent('filechooser');
await channelMenu.addBookmarkFile.click();
const fileChooser = await fileChooserPromise;
await fileChooser.setFiles(path.resolve('asset/mattermost-icon_128x128.png'));
// # Confirm the file bookmark
await channelsPage.bookmarkCreateModal.toBeVisible();
await channelsPage.bookmarkCreateModal.addButton.click();
// * Verify the file bookmark appears in the channel bookmarks bar
await channelsPage.channelBookmarksBar.toBeVisible();
await expect(channelsPage.channelBookmarksBar.getBookmark(/mattermost-icon/i)).toBeVisible();
});

View File

@@ -0,0 +1,91 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test, testConfig} from '@mattermost/playwright-lib';
import {createLinkBookmark, createLinkBookmarks} from './support';
/**
* @objective Verify the bookmarks bar remains visible and usable with an announcement banner present.
*/
test('MM-T5609 displays the bookmarks bar correctly with an announcement banner', {tag: '@channels'}, async ({pw}) => {
const {adminClient, team, user, userClient} = await pw.initSetup();
const channel = await adminClient.createPublicChannel(team.id, `Banner ${pw.random.id()}`);
await adminClient.addToChannel(user.id, channel.id);
await createLinkBookmark(userClient, channel.id, 'Mattermost Community', 'https://community.mattermost.com');
const bannerText = `Announcement ${pw.random.id()}`;
// # Enable an announcement banner above a channel with a bookmark
await adminClient.patchConfig({
AnnouncementSettings: {
EnableBanner: true,
BannerText: bannerText,
},
} as any);
const {channelsPage, page} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, channel.name);
// * Verify both the announcement and bookmark display correctly
await expect(page.getByText(bannerText, {exact: true})).toBeVisible();
await channelsPage.channelBookmarksBar.toBeVisible();
await expect(channelsPage.channelBookmarksBar.getBookmark('Mattermost Community')).toBeVisible();
});
/**
* @objective Verify external bookmarks open in a new tab and internal bookmarks navigate within Mattermost.
*/
test('MM-T5611 opens external and internal bookmark links', {tag: '@channels'}, async ({pw}) => {
// # Create external and internal link bookmarks
const {adminClient, team, user, userClient} = await pw.initSetup();
const channel = await adminClient.createPublicChannel(team.id, `Open ${pw.random.id()}`);
await adminClient.addToChannel(user.id, channel.id);
const {channelsPage, page} = await pw.testBrowser.login(user);
await createLinkBookmark(userClient, channel.id, 'External site', 'https://example.com');
await createLinkBookmark(
userClient,
channel.id,
'Town Square',
new URL(`/${team.name}/channels/town-square`, testConfig.baseURL).toString(),
);
await channelsPage.goto(team.name, channel.name);
// # Open the external bookmark
const popupPromise = page.waitForEvent('popup');
await channelsPage.channelBookmarksBar.getBookmark('External site').click();
const popup = await popupPromise;
// * Verify it opens externally in a new tab
await expect.poll(() => popup.url()).toContain('example.com');
await popup.close();
// # Open the internal bookmark
await channelsPage.channelBookmarksBar.getBookmark('Town Square').click();
// * Verify it navigates to Town Square in Mattermost
await expect.poll(() => page.url()).toContain(`/${team.name}/channels/town-square`);
});
/**
* @objective Verify bookmarks beyond the visible bar remain accessible through the overflow menu.
*/
test(
'MM-T5612 provides overflow access when the bookmarks bar reaches its visible limit',
{tag: '@channels'},
async ({pw}) => {
// # Create enough bookmarks to overflow the visible bar
const {adminClient, team, user, userClient} = await pw.initSetup();
const channel = await adminClient.createPublicChannel(team.id, `Overflow ${pw.random.id()}`);
await adminClient.addToChannel(user.id, channel.id);
await createLinkBookmarks(userClient, channel.id, 12);
const {channelsPage, page} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, channel.name);
await channelsPage.channelBookmarksBar.toBeVisible();
// * Verify the overflow control exposes the last bookmark
const overflowButton = channelsPage.channelBookmarksBar.getOverflowButton();
await expect(overflowButton).toBeVisible();
await overflowButton.click();
await expect(page.getByRole('menuitem', {name: /Bookmark 12/})).toBeVisible();
},
);

View File

@@ -0,0 +1,129 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test} from '@mattermost/playwright-lib';
import {createLinkBookmark} from './support';
/**
* @objective Verify a bookmark's URL and title can be edited and saved.
*/
test('MM-T5610 edits a bookmark URL and title', {tag: '@channels'}, async ({pw}) => {
const {adminClient, team, user, userClient} = await pw.initSetup();
const channel = await adminClient.createPublicChannel(team.id, `Edit ${pw.random.id()}`);
await adminClient.addToChannel(user.id, channel.id);
await createLinkBookmark(userClient, channel.id, 'Community Server', 'https://community.mattermost.com');
const {channelsPage} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, channel.name);
const editModal = channelsPage.getBookmarkEditModal();
// # Open the bookmark editor and change its URL and title
await channelsPage.channelBookmarksBar.openBookmarkMenu('Community Server');
await channelsPage.channelBookmarksBar.editMenuItem.click();
await editModal.toBeVisible();
await editModal.linkInput.fill('https://hub.mattermost.com');
await expect(editModal.titleInput).toHaveValue('hub.mattermost.com');
await expect(editModal.saveButton).toBeEnabled();
await editModal.titleInput.fill('Hub Server');
await editModal.saveButton.click();
// * Verify the updated bookmark title and link
await expect(channelsPage.channelBookmarksBar.getBookmark('Hub Server')).toBeVisible();
await expect(channelsPage.channelBookmarksBar.getBookmark('Hub Server')).toHaveAttribute(
'href',
/^https:\/\/hub\.mattermost\.com/,
);
});
/**
* @objective Verify users without bookmark-management permissions can only open or copy bookmarks.
*/
test('MM-T5615 restricts bookmark management to users with permission', {tag: '@channels'}, async ({pw}) => {
const {adminClient, team, user, userClient} = await pw.initSetup();
const channel = await adminClient.createPublicChannel(team.id, `Permissions ${pw.random.id()}`);
await adminClient.addToChannel(user.id, channel.id);
await createLinkBookmark(userClient, channel.id, 'First link', 'https://example.com/first');
await createLinkBookmark(userClient, channel.id, 'Second link', 'https://example.com/second');
const scheme = await adminClient.createScheme({
display_name: `Bookmark permissions ${pw.random.id()}`,
scope: 'team',
});
const channelUserRole = await adminClient.getRoleByName(scheme.default_channel_user_role);
const restrictedPermissions = channelUserRole.permissions.filter((permission) => !permission.includes('bookmark'));
// # Assign an isolated team scheme without bookmark-management permissions
await adminClient.patchRole(channelUserRole.id, {permissions: restrictedPermissions});
await adminClient.updateTeamScheme(team.id, scheme.id);
const {channelsPage, page} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, channel.name);
await channelsPage.channelBookmarksBar.toBeVisible();
// * Verify add, edit, and delete controls are unavailable
await expect(channelsPage.channelBookmarksBar.addBookmarkButton).not.toBeVisible();
await channelsPage.channelBookmarksBar.openBookmarkMenu('First link');
await expect(channelsPage.channelBookmarksBar.openMenuItem).toBeVisible();
await expect(channelsPage.channelBookmarksBar.copyLinkMenuItem).toBeVisible();
await expect(channelsPage.channelBookmarksBar.editMenuItem).not.toBeVisible();
await expect(channelsPage.channelBookmarksBar.deleteMenuItem).not.toBeVisible();
await page.keyboard.press('Escape');
// * Verify bookmarks render in their original order
const bookmarkLinks = channelsPage.channelBookmarksBar.getBookmarkLinks();
await expect(bookmarkLinks).toHaveText(['First link', 'Second link']);
const firstLink = channelsPage.channelBookmarksBar.getBookmark('First link');
await firstLink.focus();
await firstLink.press('Space');
await firstLink.press('ArrowRight');
await firstLink.press('Space');
// * Verify the keyboard reorder attempt did not change the bookmark order or link
await expect(bookmarkLinks).toHaveText(['First link', 'Second link']);
await expect(channelsPage.channelBookmarksBar.getBookmark('First link')).toHaveAttribute(
'href',
/^https:\/\/example\.com\/first/,
);
});
/**
* @objective Verify archived channels allow opening/copying bookmarks but prevent add, edit, delete, and reorder.
*/
test('MM-T5725 prevents bookmark management in an archived channel', {tag: '@channels'}, async ({pw}) => {
const {adminClient, team, user, userClient} = await pw.initSetup();
const channel = await adminClient.createPublicChannel(team.id, `Archived ${pw.random.id()}`);
await adminClient.addToChannel(user.id, channel.id);
await createLinkBookmark(userClient, channel.id, 'First link', 'https://example.com/first');
await createLinkBookmark(userClient, channel.id, 'Second link', 'https://example.com/second');
// # Archive a channel containing two bookmarks
const {channelsPage, page} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, channel.name);
await channelsPage.archiveChannel();
// * Verify bookmark management controls are unavailable
await expect(channelsPage.channelBookmarksBar.addBookmarkButton).not.toBeVisible();
await channelsPage.channelBookmarksBar.openBookmarkMenu('First link');
await expect(channelsPage.channelBookmarksBar.openMenuItem).toBeVisible();
await expect(channelsPage.channelBookmarksBar.copyLinkMenuItem).toBeVisible();
await expect(channelsPage.channelBookmarksBar.editMenuItem).not.toBeVisible();
await expect(channelsPage.channelBookmarksBar.deleteMenuItem).not.toBeVisible();
await page.keyboard.press('Escape');
// * Verify bookmarks render in their original order
const bookmarkLinks = channelsPage.channelBookmarksBar.getBookmarkLinks();
await expect(bookmarkLinks).toHaveText(['First link', 'Second link']);
const firstLink = channelsPage.channelBookmarksBar.getBookmark('First link');
await firstLink.focus();
await firstLink.press('Space');
await firstLink.press('ArrowRight');
await firstLink.press('Space');
// * Verify the keyboard reorder attempt did not change the bookmark order or link
await expect(bookmarkLinks).toHaveText(['First link', 'Second link']);
await expect(channelsPage.channelBookmarksBar.getBookmark('First link')).toHaveAttribute(
'href',
/^https:\/\/example\.com\/first/,
);
});

View File

@@ -0,0 +1,65 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test, type ChannelsPage} from '@mattermost/playwright-lib';
import {addFileBookmark} from './support';
const fileName = 'sample_text_file.txt';
async function searchFiles(channelsPage: ChannelsPage) {
await channelsPage.globalHeader.openSearch();
await channelsPage.searchBox.toBeVisible();
await channelsPage.searchBox.searchInput.fill(fileName);
await channelsPage.searchBox.searchInput.press('Enter');
await channelsPage.searchResultsPanel.toBeVisible();
await channelsPage.searchResultsPanel.filesTab.click();
}
/**
* @objective Verify a file attached as a bookmark appears in Files search results.
*/
test('MM-T5613 finds a file bookmark in Files search results', {tag: '@channels'}, async ({pw}) => {
const {adminClient, team, user} = await pw.initSetup();
const channel = await adminClient.createPublicChannel(team.id, `Search ${pw.random.id()}`);
await adminClient.addToChannel(user.id, channel.id);
const {channelsPage, page} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, channel.name);
// # Add a file bookmark and search for its filename
await addFileBookmark(page, channelsPage);
await searchFiles(channelsPage);
// * Verify the file bookmark appears in Files results
await expect(channelsPage.searchResultsPanel.container.getByText(fileName, {exact: true})).toBeVisible();
});
/**
* @objective Verify deleting a file bookmark removes its file from Files search results.
*/
test('MM-T5614 removes a deleted file bookmark from Files search results', {tag: '@channels'}, async ({pw}) => {
const {adminClient, team, user} = await pw.initSetup();
const channel = await adminClient.createPublicChannel(team.id, `Delete ${pw.random.id()}`);
await adminClient.addToChannel(user.id, channel.id);
const {channelsPage, page} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, channel.name);
// # Add a file bookmark and confirm it is searchable
await addFileBookmark(page, channelsPage);
await searchFiles(channelsPage);
await expect(channelsPage.searchResultsPanel.container.getByText(fileName, {exact: true})).toBeVisible();
await page.keyboard.press('ControlOrMeta+.');
await expect(channelsPage.searchResultsPanel.container).not.toBeVisible();
// # Delete the file bookmark
await channelsPage.channelBookmarksBar.openBookmarkMenu(fileName);
await channelsPage.channelBookmarksBar.deleteMenuItem.click();
await expect(channelsPage.channelBookmarksBar.deleteDialog).toBeVisible();
await channelsPage.channelBookmarksBar.confirmDeleteButton.click();
// * Verify the deleted file no longer appears in Files results
await searchFiles(channelsPage);
await expect(channelsPage.searchResultsPanel.container.getByText(fileName, {exact: true})).not.toBeVisible();
});

View File

@@ -0,0 +1,96 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test} from '@mattermost/playwright-lib';
import {createLinkBookmark} from './support';
/**
* @objective Verify a bookmark without favicon metadata displays the fallback link icon.
*/
test('MM-T5605 uses a fallback icon when a link has no favicon', {tag: '@channels'}, async ({pw}) => {
// # Create a link bookmark without favicon metadata
const {adminClient, team, user, userClient} = await pw.initSetup();
const channel = await adminClient.createPublicChannel(team.id, `Fallback ${pw.random.id()}`);
await adminClient.addToChannel(user.id, channel.id);
await createLinkBookmark(userClient, channel.id, 'No favicon', 'https://invalid.example.test');
const {channelsPage} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, channel.name);
await channelsPage.channelBookmarksBar.toBeVisible();
// * Verify the fallback link icon is used
await expect(channelsPage.channelBookmarksBar.getBookmarkIcon('No favicon')).toHaveAttribute(
'data-icon-kind',
'link-fallback',
);
});
/**
* @objective Verify a bookmark favicon can be changed to an emoji and reverted to its fallback icon.
*/
test(
'MM-T5606 MM-T5607 changes a bookmark favicon to an emoji and restores the fallback',
{tag: '@channels'},
async ({pw}) => {
const {adminClient, team, user, userClient} = await pw.initSetup();
const channel = await adminClient.createPublicChannel(team.id, `Icon ${pw.random.id()}`);
await adminClient.addToChannel(user.id, channel.id);
await createLinkBookmark(userClient, channel.id, 'Editable icon', 'https://invalid.example.test');
const {channelsPage} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, channel.name);
await channelsPage.channelBookmarksBar.toBeVisible();
const editModal = channelsPage.getBookmarkEditModal();
// # Edit the bookmark and choose an emoji icon
await channelsPage.channelBookmarksBar.openBookmarkMenu('Editable icon');
await channelsPage.channelBookmarksBar.editMenuItem.click();
await editModal.toBeVisible();
await editModal.selectEmoji('smile');
await editModal.saveButton.click();
// * Verify the bookmark now uses an emoji icon
await expect(channelsPage.channelBookmarksBar.getBookmarkIcon('Editable icon')).toHaveAttribute(
'data-icon-kind',
'emoji',
);
// # Edit again and remove the emoji
await channelsPage.channelBookmarksBar.openBookmarkMenu('Editable icon');
await channelsPage.channelBookmarksBar.editMenuItem.click();
await editModal.toBeVisible();
await editModal.removeEmojiButton.click();
await editModal.saveButton.click();
// * Verify the fallback icon is restored
await expect(channelsPage.channelBookmarksBar.getBookmarkIcon('Editable icon')).toHaveAttribute(
'data-icon-kind',
'link-fallback',
);
},
);
/**
* @objective Verify an invalid URL shows an error and cannot be saved as a bookmark.
*/
test('MM-T5608 rejects an invalid bookmark URL', {tag: '@channels'}, async ({pw}) => {
const {adminClient, team, user} = await pw.initSetup();
const channel = await adminClient.createPublicChannel(team.id, `Invalid ${pw.random.id()}`);
await adminClient.addToChannel(user.id, channel.id);
const {channelsPage} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, channel.name);
// # Open Add bookmark and enter invalid URL text
const channelMenu = await channelsPage.openChannelMenu();
await channelMenu.openBookmarksSubmenu();
await channelMenu.addBookmarkLink.click();
await channelsPage.bookmarkCreateModal.toBeVisible();
await channelsPage.bookmarkCreateModal.linkInput.fill('this is not a URL');
// * Verify the validation error appears and saving is disabled
await expect(channelsPage.bookmarkCreateModal.invalidLinkMessage).toBeVisible();
await expect(channelsPage.bookmarkCreateModal.addButton).toBeDisabled();
});

View File

@@ -0,0 +1,31 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test} from '@mattermost/playwright-lib';
/**
* @objective Verify that entering a link in the bookmark create modal auto-fills the bookmark title from the
* link.
*/
test('MM-T5604 auto-fills the bookmark title from the entered link', {tag: '@channels'}, async ({pw}) => {
const {user, team} = await pw.initSetup();
const {channelsPage} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, 'town-square');
await channelsPage.toBeVisible();
// # Open the bookmark create modal via the channel menu's Bookmarks Bar submenu
const channelMenu = await channelsPage.openChannelMenu();
await channelMenu.openBookmarksSubmenu();
await channelMenu.addBookmarkLink.click();
await channelsPage.bookmarkCreateModal.toBeVisible();
// # Enter a link
await channelsPage.bookmarkCreateModal.linkInput.fill('https://www.amazon.com');
// * Verify the title field is auto-filled from the link
await expect(channelsPage.bookmarkCreateModal.titleInput).toHaveValue(/amazon/i);
// # Cancel without saving
await channelsPage.bookmarkCreateModal.cancelButton.click();
await channelsPage.bookmarkCreateModal.notToBeVisible();
});

View File

@@ -0,0 +1,56 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import path from 'node:path';
import type {Client4} from '@mattermost/client';
import type {ChannelBookmark} from '@mattermost/types/channel_bookmarks';
import type {Page} from '@playwright/test';
import type {ChannelsPage} from '@mattermost/playwright-lib';
export async function createLinkBookmark(
client: Client4,
channelId: string,
displayName: string,
linkUrl: string,
options: {emoji?: string; imageUrl?: string} = {},
): Promise<ChannelBookmark> {
return client.createChannelBookmark(
channelId,
{
display_name: displayName,
link_url: linkUrl,
type: 'link',
emoji: options.emoji,
image_url: options.imageUrl,
},
'',
);
}
export async function createLinkBookmarks(client: Client4, channelId: string, count: number) {
const bookmarks: ChannelBookmark[] = [];
for (let index = 0; index < count; index++) {
bookmarks.push(
await createLinkBookmark(
client,
channelId,
`Bookmark ${index + 1}`,
`https://example.com/bookmark-${index + 1}`,
),
);
}
return bookmarks;
}
export async function addFileBookmark(page: Page, channelsPage: ChannelsPage, fileName = 'sample_text_file.txt') {
const channelMenu = await channelsPage.openChannelMenu();
await channelMenu.openBookmarksSubmenu();
const fileChooserPromise = page.waitForEvent('filechooser');
await channelMenu.addBookmarkFile.click();
const fileChooser = await fileChooserPromise;
await fileChooser.setFiles(path.resolve('asset', fileName));
await channelsPage.bookmarkCreateModal.toBeVisible();
await channelsPage.bookmarkCreateModal.addButton.click();
}