MM-59854 Fully allow at mentions in message attachment field values and add E2E tests (#28018)
* Add descriptions to test cases for getNeededAtMentionedUsernames * MM-59854 Load users who are at-mentioned in message attachment fields * MM-59854 Add server support for at-mentioning users in message attachment fields * Migrate support/external_commands from JS to TS * MM-59584 Ensure that at-mentions never show in other message attachment fields * MM-59584 Add E2E tests for how we load users based on at mentions * Use new E2E test helpers in other places * Update snapshots
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
3e84d20dbe
Коммит
46cad5c552
@@ -424,6 +424,7 @@ exports[`components/post_view/MessageAttachment should match snapshot when the a
|
||||
message="Do you like https://mattermost.com?"
|
||||
options={
|
||||
Object {
|
||||
"atMentions": false,
|
||||
"autolinkedUrlSchemes": Array [],
|
||||
"mentionHighlight": false,
|
||||
"renderer": LinkOnlyRenderer {
|
||||
@@ -469,6 +470,7 @@ exports[`components/post_view/MessageAttachment should match snapshot when the a
|
||||
message="Do you like :pizza:?"
|
||||
options={
|
||||
Object {
|
||||
"atMentions": false,
|
||||
"autolinkedUrlSchemes": Array [],
|
||||
"mentionHighlight": false,
|
||||
"renderer": LinkOnlyRenderer {
|
||||
@@ -514,6 +516,7 @@ exports[`components/post_view/MessageAttachment should match snapshot when the a
|
||||
message="Don't you like emojis?"
|
||||
options={
|
||||
Object {
|
||||
"atMentions": false,
|
||||
"autolinkedUrlSchemes": Array [],
|
||||
"mentionHighlight": false,
|
||||
"renderer": LinkOnlyRenderer {
|
||||
@@ -559,6 +562,7 @@ exports[`components/post_view/MessageAttachment should match snapshot when the f
|
||||
message="footer"
|
||||
options={
|
||||
Object {
|
||||
"atMentions": false,
|
||||
"autolinkedUrlSchemes": Array [],
|
||||
"mentionHighlight": false,
|
||||
"renderer": LinkOnlyRenderer {
|
||||
@@ -620,6 +624,7 @@ exports[`components/post_view/MessageAttachment should match value on getFieldsT
|
||||
message="title_1"
|
||||
options={
|
||||
Object {
|
||||
"atMentions": false,
|
||||
"markdown": false,
|
||||
"mentionHighlight": false,
|
||||
}
|
||||
@@ -654,6 +659,7 @@ exports[`components/post_view/MessageAttachment should match value on getFieldsT
|
||||
message="title_2"
|
||||
options={
|
||||
Object {
|
||||
"atMentions": false,
|
||||
"markdown": false,
|
||||
"mentionHighlight": false,
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ export default class MessageAttachment extends React.PureComponent<Props, State>
|
||||
let rowPos = 0;
|
||||
let lastWasLong = false;
|
||||
let nrTables = 0;
|
||||
const markdown = {markdown: false, mentionHighlight: false};
|
||||
const markdown = {markdown: false, mentionHighlight: false, atMentions: false};
|
||||
|
||||
fields.forEach((field: MessageAttachmentField, i: number) => {
|
||||
if (rowPos === 2 || !(field.short === true) || lastWasLong) {
|
||||
@@ -421,6 +421,7 @@ export default class MessageAttachment extends React.PureComponent<Props, State>
|
||||
<Markdown
|
||||
message={attachment.title}
|
||||
options={{
|
||||
atMentions: false,
|
||||
mentionHighlight: false,
|
||||
renderer: new LinkOnlyRenderer(),
|
||||
autolinkedUrlSchemes: [],
|
||||
|
||||
@@ -570,7 +570,7 @@ describe('Actions.Posts', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('getNeededAtMentionedUsernames', async () => {
|
||||
describe('getNeededAtMentionedUsernames', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
users: {
|
||||
@@ -592,65 +592,55 @@ describe('Actions.Posts', () => {
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
expect(
|
||||
Actions.getNeededAtMentionedUsernamesAndGroups(state, [
|
||||
TestHelper.getPostMock({message: 'aaa'}),
|
||||
])).toEqual(
|
||||
new Set(),
|
||||
);
|
||||
|
||||
expect(
|
||||
Actions.getNeededAtMentionedUsernamesAndGroups(state, [
|
||||
TestHelper.getPostMock({message: '@aaa'}),
|
||||
])).toEqual(
|
||||
new Set(),
|
||||
);
|
||||
|
||||
expect(
|
||||
Actions.getNeededAtMentionedUsernamesAndGroups(state, [
|
||||
TestHelper.getPostMock({message: '@zzz'}),
|
||||
])).toEqual(
|
||||
new Set(),
|
||||
);
|
||||
|
||||
expect(
|
||||
Actions.getNeededAtMentionedUsernamesAndGroups(state, [
|
||||
TestHelper.getPostMock({message: '@aaa @bbb @ccc @zzz'}),
|
||||
])).toEqual(
|
||||
new Set(['bbb', 'ccc']),
|
||||
);
|
||||
|
||||
expect(
|
||||
Actions.getNeededAtMentionedUsernamesAndGroups(state, [
|
||||
TestHelper.getPostMock({message: '@bbb. @ccc.ddd'}),
|
||||
])).toEqual(
|
||||
new Set(['bbb.', 'bbb', 'ccc.ddd']),
|
||||
);
|
||||
|
||||
expect(
|
||||
Actions.getNeededAtMentionedUsernamesAndGroups(state, [
|
||||
TestHelper.getPostMock({message: '@bbb- @ccc-ddd'}),
|
||||
])).toEqual(
|
||||
new Set(['bbb-', 'bbb', 'ccc-ddd']),
|
||||
);
|
||||
|
||||
expect(
|
||||
Actions.getNeededAtMentionedUsernamesAndGroups(state, [
|
||||
TestHelper.getPostMock({message: '@bbb_ @ccc_ddd'}),
|
||||
])).toEqual(
|
||||
new Set(['bbb_', 'ccc_ddd']),
|
||||
);
|
||||
|
||||
expect(
|
||||
Actions.getNeededAtMentionedUsernamesAndGroups(state, [
|
||||
TestHelper.getPostMock({message: '(@bbb/@ccc) ddd@eee'}),
|
||||
])).toEqual(
|
||||
new Set(['bbb', 'ccc']),
|
||||
);
|
||||
|
||||
expect(
|
||||
Actions.getNeededAtMentionedUsernamesAndGroups(state, [
|
||||
TestHelper.getPostMock({
|
||||
const testCases = [
|
||||
{
|
||||
name: "shouldn't return anything when no users are at-mentioned",
|
||||
input: TestHelper.getPostMock({message: 'aaa'}),
|
||||
expected: new Set(),
|
||||
},
|
||||
{
|
||||
name: "shouldn't return anything for a user that's already loaded",
|
||||
input: TestHelper.getPostMock({message: '@aaa'}),
|
||||
expected: new Set(),
|
||||
},
|
||||
{
|
||||
name: "shouldn't return anything for a group that's already loaded",
|
||||
input: TestHelper.getPostMock({message: '@zzz'}),
|
||||
expected: new Set(),
|
||||
},
|
||||
{
|
||||
name: 'should return any unrecognized at-mentions',
|
||||
input: TestHelper.getPostMock({message: '@aaa @bbb @ccc @zzz'}),
|
||||
expected: new Set(['bbb', 'ccc']),
|
||||
},
|
||||
{
|
||||
name: 'should return at-mentions followed by period both with and without the period',
|
||||
input: TestHelper.getPostMock({message: '@bbb. @ccc.ddd'}),
|
||||
expected: new Set(['bbb.', 'bbb', 'ccc.ddd']),
|
||||
},
|
||||
{
|
||||
name: 'should return at-mentions followed by hyphen both with and without the hyphen',
|
||||
input: TestHelper.getPostMock({message: '@bbb- @ccc-ddd'}),
|
||||
expected: new Set(['bbb-', 'bbb', 'ccc-ddd']),
|
||||
},
|
||||
{
|
||||
name: 'should return at-mentions followed by underscores with the underscore',
|
||||
input: TestHelper.getPostMock({message: '@bbb_ @ccc_ddd'}),
|
||||
expected: new Set(['bbb_', 'ccc_ddd']),
|
||||
},
|
||||
{
|
||||
name: 'should return at-mentions in brackets',
|
||||
input: TestHelper.getPostMock({message: '(@bbb/@ccc)'}),
|
||||
expected: new Set(['bbb', 'ccc']),
|
||||
},
|
||||
{
|
||||
name: "shouldn't return anything when an at sign is in the middle of a word",
|
||||
input: TestHelper.getPostMock({message: 'ddd@eee'}),
|
||||
expected: new Set(),
|
||||
},
|
||||
{
|
||||
name: 'should return at-mentions from inside message attachment props text and pretext',
|
||||
input: TestHelper.getPostMock({
|
||||
message: '@aaa @bbb',
|
||||
props: {
|
||||
attachments: [
|
||||
@@ -659,23 +649,55 @@ describe('Actions.Posts', () => {
|
||||
],
|
||||
},
|
||||
}),
|
||||
]),
|
||||
).toEqual(
|
||||
new Set(['bbb', 'ccc', 'ddd', 'eee', 'fff', 'ggg']),
|
||||
);
|
||||
expected: new Set(['bbb', 'ccc', 'ddd', 'eee', 'fff', 'ggg']),
|
||||
},
|
||||
{
|
||||
name: 'should return at-mentions from inside message attachment field values but not their titles',
|
||||
input: TestHelper.getPostMock({
|
||||
props: {
|
||||
attachments: [
|
||||
{
|
||||
fields: [
|
||||
{title: '@bbb', value: '@ccc'},
|
||||
{value: '@ddd'},
|
||||
],
|
||||
},
|
||||
{
|
||||
fields: [
|
||||
{title: '@eee', value: '@fff'},
|
||||
{value: '@ggg'},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
expected: new Set(['ccc', 'ddd', 'fff', 'ggg']),
|
||||
},
|
||||
];
|
||||
|
||||
// should never try to request usernames matching special mentions
|
||||
expect(
|
||||
Actions.getNeededAtMentionedUsernamesAndGroups(state, [
|
||||
TestHelper.getPostMock({message: '@all'}),
|
||||
TestHelper.getPostMock({message: '@here'}),
|
||||
TestHelper.getPostMock({message: '@channel'}),
|
||||
TestHelper.getPostMock({message: '@all.'}),
|
||||
TestHelper.getPostMock({message: '@here.'}),
|
||||
TestHelper.getPostMock({message: '@channel.'}),
|
||||
])).toEqual(
|
||||
new Set(),
|
||||
);
|
||||
for (const specialMention of [
|
||||
'@all',
|
||||
'@here',
|
||||
'@channel',
|
||||
'@all.',
|
||||
'@here.',
|
||||
'@channel.',
|
||||
]) {
|
||||
testCases.push({
|
||||
name: `should never return special mentions (${specialMention})`,
|
||||
input: TestHelper.getPostMock({message: specialMention}),
|
||||
expected: new Set(),
|
||||
});
|
||||
}
|
||||
|
||||
for (const testCase of testCases) {
|
||||
test(testCase.name, () => {
|
||||
expect(Actions.getNeededAtMentionedUsernamesAndGroups(
|
||||
state,
|
||||
[testCase.input],
|
||||
)).toEqual(testCase.expected);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('getPostsSince', async () => {
|
||||
|
||||
@@ -1090,6 +1090,12 @@ export function getNeededAtMentionedUsernamesAndGroups(state: GlobalState, posts
|
||||
for (const attachment of post.props.attachments) {
|
||||
findNeededUsernamesAndGroups(attachment.pretext);
|
||||
findNeededUsernamesAndGroups(attachment.text);
|
||||
|
||||
if (attachment.fields) {
|
||||
for (const field of attachment.fields) {
|
||||
findNeededUsernamesAndGroups(field.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user