Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions e2e-tests/playwright/lib/src/ui/components/channels/post_create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export default class ChannelsPostCreate {
readonly suggestionOptions;
readonly selectedSuggestion;
readonly filePreview;
readonly previewButton;
readonly previewArea;

// Burn-on-Read elements
readonly burnOnReadButton;
Expand All @@ -46,6 +48,8 @@ export default class ChannelsPostCreate {
this.suggestionOptions = this.suggestionList.getByRole('option');
this.selectedSuggestion = this.suggestionList.getByTestId('suggestion-selected');
this.filePreview = container.getByTestId('file-preview-container');
this.previewButton = container.getByRole('button', {name: 'preview'});
this.previewArea = container.locator('.textbox-preview-area');

// Burn-on-Read elements
// Use a flexible locator that matches the aria-label pattern
Expand Down Expand Up @@ -192,6 +196,16 @@ export default class ChannelsPostCreate {
await this.emojiButton.click();
}

async togglePreview() {
await expect(this.previewButton).toBeVisible();
await this.previewButton.click();
}

async clickMentionInPreview() {
await expect(this.previewArea).toBeVisible();
await this.previewArea.locator('.mention-link').click();
}

async waitUntilFilePreviewContains(files: string[], timeout = duration.ten_sec) {
await waitUntil(
async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import {expect, setWysiwygUserPreference, test} from '@mattermost/playwright-lib';

/**
* @objective Clicking a user at-mention in the composer preview opens the profile popover
* and does not post the draft.
*
* @precondition Two users on the same team. The markdown composer preview is available
* (WYSIWYG editor preference is off).
*/
test(
'MM-67123 clicking a user mention in composer preview opens the profile popover',
{tag: '@mentions'},
async ({pw}) => {
// # Create two users on the same team and disable the WYSIWYG editor so preview is available
const {adminClient, user, userClient, team} = await pw.initSetup();
await setWysiwygUserPreference(userClient, user.id, false);

const mentionedUser = await adminClient.createUser(await pw.random.user('mentioned'), '', '');
await adminClient.addToTeam(team.id, mentionedUser.id);
const townSquare = await adminClient.getChannelByName(team.id, 'town-square');
await adminClient.addToChannel(mentionedUser.id, townSquare.id);

const {channelsPage} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, 'town-square');
await channelsPage.toBeVisible();

const unique = `preview-mention-${pw.random.id()}`;
const {postCreate} = channelsPage.centerView;

// # Type a draft that mentions the other user via autocomplete so the mention resolves
await postCreate.writeMessage(`@${mentionedUser.username}`);
await expect(postCreate.suggestionList).toBeVisible();
await postCreate.suggestionOptions.first().click();
await postCreate.input.pressSequentially(` ${unique}`);
const draft = await postCreate.getInputValue();

// # Show the composer markdown preview
await postCreate.togglePreview();
await expect(postCreate.previewArea).toBeVisible();
await expect(postCreate.previewArea).toContainText(`@${mentionedUser.username}`);
await expect(postCreate.previewArea).toContainText(unique);

// # Click the rendered mention in the preview
await postCreate.clickMentionInPreview();

// * The mentioned user's profile popover opens
await expect(channelsPage.userProfilePopover.container).toBeVisible();
await expect(channelsPage.userProfilePopover.container).toContainText(`@${mentionedUser.username}`);

// * The draft remains in the composer and is not posted
await expect(postCreate.input).toHaveValue(draft);
await expect(postCreate.previewArea).toContainText(unique);

const lastPost = await channelsPage.getLastPost();
await expect(lastPost.container).not.toContainText(unique);
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ exports[`components/UserList should match default snapshot when there are users
aria-haspopup="dialog"
class="status-wrapper style--none"
style="border-radius: 50%; width: 32px; height: 32px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -53,6 +54,7 @@ exports[`components/UserList should match default snapshot when there are users
aria-expanded="false"
aria-haspopup="dialog"
class="user-popover style--none"
type="button"
>
Someone
</button>
Expand Down Expand Up @@ -80,6 +82,7 @@ exports[`components/UserList should match default snapshot when there are users
aria-haspopup="dialog"
class="status-wrapper style--none"
style="border-radius: 50%; width: 32px; height: 32px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -108,6 +111,7 @@ exports[`components/UserList should match default snapshot when there are users
aria-expanded="false"
aria-haspopup="dialog"
class="user-popover style--none"
type="button"
>
Someone
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ exports[`components/admin_console/admin_user_card/admin_user_card should match d
aria-haspopup="dialog"
class="status-wrapper style--none admin-user-card"
style="border-radius: 50%; width: 128px; height: 128px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -81,6 +82,7 @@ exports[`components/admin_console/admin_user_card/admin_user_card should match s
aria-haspopup="dialog"
class="status-wrapper style--none admin-user-card"
style="border-radius: 50%; width: 128px; height: 128px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -142,6 +144,7 @@ exports[`components/admin_console/admin_user_card/admin_user_card should match s
aria-haspopup="dialog"
class="status-wrapper style--none admin-user-card"
style="border-radius: 50%; width: 128px; height: 128px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -201,6 +204,7 @@ exports[`components/admin_console/admin_user_card/admin_user_card should match s
aria-haspopup="dialog"
class="status-wrapper style--none admin-user-card"
style="border-radius: 50%; width: 128px; height: 128px;"
type="button"
>
<span
class="profile-icon "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ exports[`SystemUserDetail should match default snapshot 1`] = `
aria-haspopup="dialog"
class="status-wrapper style--none admin-user-card"
style="border-radius: 50%; width: 128px; height: 128px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -341,6 +342,7 @@ exports[`SystemUserDetail should match snapshot if MFA is enabled 1`] = `
aria-haspopup="dialog"
class="status-wrapper style--none admin-user-card"
style="border-radius: 50%; width: 128px; height: 128px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -644,6 +646,7 @@ exports[`SystemUserDetail should not fetch CPA data if disabled 1`] = `
aria-haspopup="dialog"
class="status-wrapper style--none admin-user-card"
style="border-radius: 50%; width: 128px; height: 128px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -947,6 +950,7 @@ exports[`SystemUserDetail should not show manage user settings button when user
aria-haspopup="dialog"
class="status-wrapper style--none admin-user-card"
style="border-radius: 50%; width: 128px; height: 128px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -1250,6 +1254,7 @@ exports[`SystemUserDetail should show manage user settings button as activated 1
aria-haspopup="dialog"
class="status-wrapper style--none admin-user-card"
style="border-radius: 50%; width: 128px; height: 128px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -1559,6 +1564,7 @@ exports[`SystemUserDetail should show manage user settings button as disabled wh
aria-haspopup="dialog"
class="status-wrapper style--none admin-user-card"
style="border-radius: 50%; width: 128px; height: 128px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -1862,6 +1868,7 @@ exports[`SystemUserDetail should show the activate user button as disabled when
aria-haspopup="dialog"
class="status-wrapper style--none admin-user-card"
style="border-radius: 50%; width: 128px; height: 128px;"
type="button"
>
<span
class="profile-icon "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ exports[`components/AtMention should match snapshot when mentioning current user
aria-expanded="false"
aria-haspopup="dialog"
class="style--none mention--highlight"
type="button"
>
<span
class="mention-link"
Expand All @@ -81,6 +82,7 @@ exports[`components/AtMention should match snapshot when mentioning user 1`] = `
aria-expanded="false"
aria-haspopup="dialog"
class="style--none"
type="button"
>
<span
class="mention-link"
Expand All @@ -97,6 +99,7 @@ exports[`components/AtMention should match snapshot when mentioning user contain
aria-expanded="false"
aria-haspopup="dialog"
class="style--none"
type="button"
>
<span
class="mention-link"
Expand All @@ -114,6 +117,7 @@ exports[`components/AtMention should match snapshot when mentioning user contain
aria-expanded="false"
aria-haspopup="dialog"
class="style--none"
type="button"
>
<span
class="mention-link"
Expand All @@ -130,6 +134,7 @@ exports[`components/AtMention should match snapshot when mentioning user followe
aria-expanded="false"
aria-haspopup="dialog"
class="style--none"
type="button"
>
<span
class="mention-link"
Expand All @@ -147,6 +152,7 @@ exports[`components/AtMention should match snapshot when mentioning user with di
aria-expanded="false"
aria-haspopup="dialog"
class="style--none"
type="button"
>
<span
class="mention-link"
Expand All @@ -163,6 +169,7 @@ exports[`components/AtMention should match snapshot when mentioning user with mi
aria-expanded="false"
aria-haspopup="dialog"
class="style--none"
type="button"
>
<span
class="mention-link"
Expand Down
15 changes: 14 additions & 1 deletion webapp/channels/src/components/at_mention/at_mention.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React from 'react';

import {General} from 'mattermost-redux/constants';

import {render, renderWithContext} from 'tests/react_testing_utils';
import {render, renderWithContext, screen} from 'tests/react_testing_utils';
import {TestHelper} from 'utils/test_helper';

import AtMention from './at_mention';
Expand Down Expand Up @@ -42,6 +42,19 @@ describe('components/AtMention', () => {
expect(container).toMatchSnapshot();
});

test('should render the mention as a non-submit button', () => {
render(
<AtMention
{...baseProps}
mentionName='user1'
>
{'(at)-user1'}
</AtMention>,
);

expect(screen.getByRole('button')).toHaveAttribute('type', 'button');
});

test('should match snapshot when mentioning user with different teammate name display setting', () => {
const {container} = render(
<AtMention
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ exports[`components/drafts/panel/panel_body should have called handleFormattedTe
aria-haspopup="dialog"
class="status-wrapper style--none"
style="border-radius: 50%; width: 32px; height: 32px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -102,6 +103,7 @@ exports[`components/drafts/panel/panel_body should match snapshot 1`] = `
aria-haspopup="dialog"
class="status-wrapper style--none"
style="border-radius: 50%; width: 32px; height: 32px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -189,6 +191,7 @@ exports[`components/drafts/panel/panel_body should match snapshot for priority 1
aria-haspopup="dialog"
class="status-wrapper style--none"
style="border-radius: 50%; width: 32px; height: 32px;"
type="button"
>
<span
class="profile-icon "
Expand Down Expand Up @@ -302,6 +305,7 @@ exports[`components/drafts/panel/panel_body should match snapshot for requested_
aria-haspopup="dialog"
class="status-wrapper style--none"
style="border-radius: 50%; width: 32px; height: 32px;"
type="button"
>
<span
class="profile-icon "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ exports[`components/ProfilePicture should match snapshot, profile and src, defau
aria-haspopup="dialog"
class="status-wrapper style--none"
style="border-radius: 50%; width: 32px; height: 32px;"
type="button"
>
<span
class="profile-icon "
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React from 'react';

import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils';
import {RootHtmlPortalId} from 'utils/constants';

import ProfilePopover from './index';

jest.mock('./profile_popover', () => ({
__esModule: true,
default: () => <div>{'profile'}</div>,
}));

describe('ProfilePopoverController', () => {
test('button triggers use type=button so they do not submit parent forms', async () => {
const handleSubmit = jest.fn((e: React.FormEvent) => {
e.preventDefault();
});

renderWithContext(
<form onSubmit={handleSubmit}>
<div id={RootHtmlPortalId}/>
<ProfilePopover
triggerComponentAs='button'
triggerComponentClass='style--none'
userId='user1'
src=''
>
{'@user1'}
</ProfilePopover>
</form>,
);

const trigger = screen.getByRole('button', {name: '@user1'});
expect(trigger).toHaveAttribute('type', 'button');

await userEvent.click(trigger);

expect(handleSubmit).not.toHaveBeenCalled();
expect(screen.getByTestId('user-profile-popover')).toBeInTheDocument();
});
});
Loading
Loading