chore: Add more (un)localized body tests

Covers a few edge cases that still fail. Changes to the unlocalizedBody
function shouldn't cause behavioural changes apart from fixing a few
edge cases.
This commit is contained in:
Nicolas Werner 2024-09-27 16:32:08 +02:00
parent c7d49695d5
commit a497a66012
No known key found for this signature in database
GPG Key ID: B38119FF80087618
2 changed files with 468 additions and 14 deletions

View File

@ -761,7 +761,10 @@ class Event extends MatrixEvent {
/// Returns a localized String representation of this event. For a
/// room list you may find [withSenderNamePrefix] useful. Set [hideReply] to
/// crop all lines starting with '>'. With [plaintextBody] it'll use the
/// plaintextBody instead of the normal body.
/// plaintextBody instead of the normal body which in practice will convert
/// the html body to a plain text body before falling back to the body. In
/// either case this function won't return the html body without converting
/// it to plain text.
/// [removeMarkdown] allow to remove the markdown formating from the event body.
/// Usefull form message preview or notifications text.
Future<String> calcLocalizedBody(MatrixLocalizations i18n,
@ -850,37 +853,41 @@ class Event extends MatrixEvent {
}
/// Calculating the body of an event regardless of localization.
String calcUnlocalizedBody(
{bool hideReply = false,
bool hideEdit = false,
bool plaintextBody = false,
bool removeMarkdown = false}) {
String calcUnlocalizedBody({
bool hideReply = false,
bool hideEdit = false,
bool plaintextBody = false,
bool removeMarkdown = false,
}) {
if (redacted) {
return 'Removed by ${senderFromMemoryOrFallback.displayName ?? senderId}';
}
var body = plaintextBody ? this.plaintextBody : this.body;
// we need to know if the message is an html message to be able to determine
// if we need to strip the reply fallback.
var htmlMessage = content['format'] != 'org.matrix.custom.html';
// Html messages will already have their reply fallback removed during the Html to Text conversion.
var mayHaveReplyFallback =
!plaintextBody || content['format'] != 'org.matrix.custom.html';
// If we have an edit, we want to operate on the new content
final newContent = content.tryGetMap<String, Object?>('m.new_content');
if (hideEdit &&
relationshipType == RelationshipTypes.edit &&
newContent != null) {
if (plaintextBody && newContent['format'] == 'org.matrix.custom.html') {
htmlMessage = true;
body = HtmlToText.convert(
newContent.tryGet<String>('formatted_body') ?? formattedText);
final newBody = newContent.tryGet<String>('formatted_body');
if (newBody != null) {
mayHaveReplyFallback = false;
body = HtmlToText.convert(newBody);
}
} else {
htmlMessage = false;
mayHaveReplyFallback = true;
body = newContent.tryGet<String>('body') ?? body;
}
}
// Hide reply fallback
// Be sure that the plaintextBody already stripped teh reply fallback,
// if the message is formatted
if (hideReply && (!plaintextBody || htmlMessage)) {
if (hideReply && mayHaveReplyFallback) {
body = body.replaceFirst(
RegExp(r'^>( \*)? <[^>]+>[^\n\r]+\r?\n(> [^\n]*\r?\n)*\r?\n'), '');
}

View File

@ -1229,6 +1229,453 @@ void main() {
expect(event2.body, 'm.room.message');
});
group('unlocalized body reply stripping', () {
int i = 0;
void testUnlocalizedBody({
required Object? body,
required Object? formattedBody,
required bool html,
Object? editBody,
Object? editFormattedBody,
bool editHtml = false,
bool isEdit = false,
required String expectation,
required bool plaintextBody,
}) {
i += 1;
test('$i', () {
final event = Event.fromJson({
'type': EventTypes.Message,
'content': {
'msgtype': 'm.text',
if (body != null) 'body': body,
if (formattedBody != null) 'formatted_body': formattedBody,
if (html) 'format': 'org.matrix.custom.html',
if (isEdit) ...{
'm.new_content': {
if (editBody != null) 'body': editBody,
if (editFormattedBody != null)
'formatted_body': editFormattedBody,
if (editHtml) 'format': 'org.matrix.custom.html',
},
'm.relates_to': {
'event_id': '\$source2',
'rel_type': RelationshipTypes.edit,
},
},
},
'event_id': '\$source',
'sender': '@alice:example.org',
}, room);
expect(
event.calcUnlocalizedBody(
hideReply: true, hideEdit: true, plaintextBody: plaintextBody),
expectation,
reason:
'event was ${event.toJson()} and plaintextBody ${plaintextBody ? "was" : "was not"} set',
);
});
}
// everything where we expect the body to be returned
testUnlocalizedBody(
expectation: 'body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: false,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
// not sure we actually want m.room.message here and not an empty string
expectation: 'm.room.message',
plaintextBody: false,
body: '',
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: false,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'm.room.message',
plaintextBody: false,
body: null,
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: false,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'm.room.message',
plaintextBody: false,
body: 5,
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: false,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: true,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'body',
plaintextBody: false,
body: 'body',
formattedBody: null,
html: true,
isEdit: false,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'body',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: false,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'body',
plaintextBody: true,
body: 'body',
formattedBody: null,
html: true,
isEdit: false,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'body',
plaintextBody: true,
body: 'body',
// do we actually expect this to then use the body?
formattedBody: '',
html: true,
isEdit: false,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'body',
plaintextBody: true,
body: 'body',
formattedBody: 5,
html: true,
isEdit: false,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: null,
editFormattedBody: null,
editHtml: true,
);
testUnlocalizedBody(
expectation: '**formatted body**',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: '**formatted body**',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: null,
editFormattedBody: null,
editHtml: true,
);
// everything where we expect the formatted body to be returned
testUnlocalizedBody(
expectation: '**formatted body**',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: false,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: '**formatted body**',
plaintextBody: true,
body: 5,
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: false,
editBody: null,
editFormattedBody: null,
editHtml: false,
);
// everything where we expect the edit body to be returned
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: true,
editBody: 'edit body',
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: true,
editBody: 'edit body',
editFormattedBody: '<b>edit formatted body</b>',
editHtml: true,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: 'edit body',
editFormattedBody: '<b>edit formatted body</b>',
editHtml: true,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: true,
editBody: 'edit body',
editFormattedBody: '<b>edit formatted body</b>',
editHtml: false,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: true,
editBody: 'edit body',
editFormattedBody: null,
editHtml: true,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: 'edit body',
editFormattedBody: 5,
editHtml: true,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: 'edit body',
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: false,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: 'edit body',
editFormattedBody: '<b>edit formatted body</b>',
editHtml: false,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: true,
editBody: 'edit body',
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: true,
editBody: 'edit body',
editFormattedBody: '<b>edit formatted body</b>',
editHtml: false,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: false,
isEdit: true,
editBody: 'edit body',
editFormattedBody: null,
editHtml: true,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: 'edit body',
editFormattedBody: null,
editHtml: false,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: 'edit body',
editFormattedBody: '<b>edit formatted body</b>',
editHtml: false,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: 'edit body',
editFormattedBody: null,
editHtml: true,
);
testUnlocalizedBody(
expectation: 'edit body',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: 'edit body',
editFormattedBody: null,
editHtml: false,
);
// everything where we expect the edit formatted body to be returned
testUnlocalizedBody(
expectation: '**edit formatted body**',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: null,
editFormattedBody: '<b>edit formatted body</b>',
editHtml: true,
);
testUnlocalizedBody(
expectation: '**edit formatted body**',
plaintextBody: true,
body: 'body',
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: 'edit body',
editFormattedBody: '<b>edit formatted body</b>',
editHtml: true,
);
testUnlocalizedBody(
expectation: '**edit formatted body**',
plaintextBody: true,
body: null,
formattedBody: '<b>formatted body</b>',
html: true,
isEdit: true,
editBody: 'edit body',
editFormattedBody: '<b>edit formatted body</b>',
editHtml: true,
);
testUnlocalizedBody(
expectation: '**edit formatted body**',
plaintextBody: true,
body: 'body',
formattedBody: null,
html: true,
isEdit: true,
editBody: 'edit body',
editFormattedBody: '<b>edit formatted body</b>',
editHtml: true,
);
});
test('getDisplayEvent', () {
final room = Room(id: '!1234', client: client);
var event = Event.fromJson({