TF-3514 Add test case for unit test HtmlAnalyzer when html content existing CID but inlineAttachments is empty
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import 'dart:collection';
|
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:core/data/constants/constant.dart';
|
import 'package:core/data/constants/constant.dart';
|
||||||
@@ -128,6 +127,7 @@ class HtmlAnalyzer {
|
|||||||
}) async {
|
}) async {
|
||||||
final document = parse(emailContent);
|
final document = parse(emailContent);
|
||||||
final listImgTag = document.querySelectorAll('img[src^="data:image/"]');
|
final listImgTag = document.querySelectorAll('img[src^="data:image/"]');
|
||||||
|
|
||||||
log('HtmlAnalyzer::replaceImageBase64ToImageCID:listImgTagLength = ${listImgTag.length} | inlineAttachments = ${inlineAttachments.length}');
|
log('HtmlAnalyzer::replaceImageBase64ToImageCID:listImgTagLength = ${listImgTag.length} | inlineAttachments = ${inlineAttachments.length}');
|
||||||
|
|
||||||
if (listImgTag.isEmpty) {
|
if (listImgTag.isEmpty) {
|
||||||
@@ -143,40 +143,45 @@ class HtmlAnalyzer {
|
|||||||
final List<Future<void>> asyncTasks = [];
|
final List<Future<void>> asyncTasks = [];
|
||||||
|
|
||||||
for (final imgTag in listImgTag) {
|
for (final imgTag in listImgTag) {
|
||||||
late final LinkedHashMap<Object, String> attributes = imgTag.attributes;
|
final attributes = imgTag.attributes;
|
||||||
final idImg = attributes['id'];
|
|
||||||
final imageSrc = attributes['src'];
|
final imageSrc = attributes['src'];
|
||||||
|
|
||||||
if (imageSrc?.isEmpty ?? true) continue;
|
if (imageSrc?.isEmpty ?? true) continue;
|
||||||
|
|
||||||
|
final idImg = attributes['id'];
|
||||||
if (idImg?.startsWith(cidPrefixKey) == true) {
|
if (idImg?.startsWith(cidPrefixKey) == true) {
|
||||||
final cid = idImg!.substring(cidPrefixKey.length).trim();
|
final cid = idImg!.substring(cidPrefixKey.length).trim();
|
||||||
attributes['src'] = '$cidPrefixKey$cid';
|
|
||||||
attributes.remove('id');
|
|
||||||
|
|
||||||
final attachment = inlineAttachments[cid];
|
final attachment = inlineAttachments[cid];
|
||||||
log('HtmlAnalyzer::replaceImageBase64ToImageCID:attachment = $attachment');
|
|
||||||
if (attachment != null) {
|
if (attachment != null) {
|
||||||
|
attributes['src'] = '$cidPrefixKey$cid';
|
||||||
|
attributes.remove('id');
|
||||||
inlineAttachmentsSet.add(attachment.toEmailBodyPart(charset: Constant.base64Charset));
|
inlineAttachmentsSet.add(attachment.toEmailBodyPart(charset: Constant.base64Charset));
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uploadUri == null) continue;
|
if (uploadUri == null) continue;
|
||||||
|
|
||||||
|
final taskId = idImg?.startsWith(cidPrefixKey) == true
|
||||||
|
? idImg!.substring(cidPrefixKey.length)
|
||||||
|
: _uuid.v1();
|
||||||
|
|
||||||
asyncTasks.add(_retrieveAttachmentFromUpload(
|
asyncTasks.add(_retrieveAttachmentFromUpload(
|
||||||
|
taskId: taskId,
|
||||||
uploadUri: uploadUri,
|
uploadUri: uploadUri,
|
||||||
base64ImageTag: imageSrc!,
|
base64ImageTag: imageSrc!,
|
||||||
).then((newAttachment) {
|
).then((attachmentRecord) {
|
||||||
if (newAttachment == null) return;
|
if (attachmentRecord == null) return;
|
||||||
|
|
||||||
final newInlineAttachment = newAttachment.toAttachmentWithDisposition(
|
final newInlineAttachment = attachmentRecord.$1.toAttachmentWithDisposition(
|
||||||
disposition: ContentDisposition.inline,
|
disposition: ContentDisposition.inline,
|
||||||
cid: _uuid.v1(),
|
cid: attachmentRecord.$2,
|
||||||
);
|
);
|
||||||
final newCid = newInlineAttachment.cid;
|
|
||||||
inlineAttachments[newCid!] = newInlineAttachment;
|
final newCid = newInlineAttachment.cid!;
|
||||||
|
inlineAttachments[newCid] = newInlineAttachment;
|
||||||
attributes['src'] = '$cidPrefixKey$newCid';
|
attributes['src'] = '$cidPrefixKey$newCid';
|
||||||
|
attributes.remove('id');
|
||||||
|
|
||||||
inlineAttachmentsSet.add(newInlineAttachment.toEmailBodyPart(charset: Constant.base64Charset));
|
inlineAttachmentsSet.add(newInlineAttachment.toEmailBodyPart(charset: Constant.base64Charset));
|
||||||
}));
|
}));
|
||||||
@@ -186,8 +191,7 @@ class HtmlAnalyzer {
|
|||||||
await Future.wait(asyncTasks);
|
await Future.wait(asyncTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
final newContent = document.body?.innerHtml ?? emailContent;
|
return Tuple2(document.body?.innerHtml ?? emailContent, inlineAttachmentsSet);
|
||||||
return Tuple2(newContent, inlineAttachmentsSet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> removeCollapsedExpandedSignatureEffect({required String emailContent}) async {
|
Future<String> removeCollapsedExpandedSignatureEffect({required String emailContent}) async {
|
||||||
@@ -210,7 +214,8 @@ class HtmlAnalyzer {
|
|||||||
return newContent;
|
return newContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Attachment?> _retrieveAttachmentFromUpload({
|
Future<(Attachment attachment, String taskId)?> _retrieveAttachmentFromUpload({
|
||||||
|
required String taskId,
|
||||||
required Uri uploadUri,
|
required Uri uploadUri,
|
||||||
required String base64ImageTag,
|
required String base64ImageTag,
|
||||||
}) async {
|
}) async {
|
||||||
@@ -218,20 +223,19 @@ class HtmlAnalyzer {
|
|||||||
final imageBytes = StringConvert.convertBase64ImageTagToBytes(base64ImageTag);
|
final imageBytes = StringConvert.convertBase64ImageTagToBytes(base64ImageTag);
|
||||||
final mediaType = StringConvert.getMediaTypeFromBase64ImageTag(base64ImageTag);
|
final mediaType = StringConvert.getMediaTypeFromBase64ImageTag(base64ImageTag);
|
||||||
log('HtmlAnalyzer::_retrieveAttachmentFromUpload: mimeType = ${mediaType?.mimeType} | imageBytesLength = ${imageBytes.length}');
|
log('HtmlAnalyzer::_retrieveAttachmentFromUpload: mimeType = ${mediaType?.mimeType} | imageBytesLength = ${imageBytes.length}');
|
||||||
final generateId = _uuid.v1();
|
|
||||||
final fileInfo = FileInfo.fromBytes(
|
final fileInfo = FileInfo.fromBytes(
|
||||||
bytes: imageBytes,
|
bytes: imageBytes,
|
||||||
name: '$generateId.${mediaType?.subtype ?? 'png'}',
|
name: '$taskId.${mediaType?.subtype ?? 'png'}',
|
||||||
type: mediaType?.mimeType,
|
type: mediaType?.mimeType,
|
||||||
);
|
);
|
||||||
|
|
||||||
final attachment = await _fileUploader.uploadAttachment(
|
final attachment = await _fileUploader.uploadAttachment(
|
||||||
UploadTaskId(generateId),
|
UploadTaskId(taskId),
|
||||||
fileInfo,
|
fileInfo,
|
||||||
uploadUri,
|
uploadUri,
|
||||||
);
|
);
|
||||||
log('HtmlAnalyzer::_retrieveAttachmentFromUpload:Attachment = $attachment');
|
log('HtmlAnalyzer::_retrieveAttachmentFromUpload:Attachment = $attachment | taskId = $taskId');
|
||||||
return attachment;
|
return (attachment, taskId);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError('HtmlAnalyzer::_retrieveAttachmentFromUpload:Exception = $e');
|
logError('HtmlAnalyzer::_retrieveAttachmentFromUpload:Exception = $e');
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -73,6 +73,37 @@ void main() {
|
|||||||
expect(result.value2.first.cid, 'test123');
|
expect(result.value2.first.cid, 'test123');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'When HTML content has an image with existing CID,\n'
|
||||||
|
'but inlineAttachments is empty,\n'
|
||||||
|
'should re-upload base64 succeeds then replace src with that CID and add attachment to result',
|
||||||
|
() async {
|
||||||
|
const htmlContent = '<img id="cid:test123" src="data:image/png;base64,iVBORw0KGgo=">';
|
||||||
|
final inlineAttachments = <String, Attachment>{};
|
||||||
|
final uploadUri = Uri.parse('https://example.com/upload');
|
||||||
|
|
||||||
|
when(mockFileUploader.uploadAttachment(any, any, any))
|
||||||
|
.thenAnswer((_) async => Attachment(
|
||||||
|
blobId: Id('test123'),
|
||||||
|
type: MediaType('image', 'png'),
|
||||||
|
disposition: ContentDisposition.inline,
|
||||||
|
cid: 'test123',
|
||||||
|
));
|
||||||
|
|
||||||
|
final result = await htmlAnalyzer.replaceImageBase64ToImageCID(
|
||||||
|
emailContent: htmlContent,
|
||||||
|
inlineAttachments: inlineAttachments,
|
||||||
|
uploadUri: uploadUri,
|
||||||
|
);
|
||||||
|
|
||||||
|
final document = parse(result.value1);
|
||||||
|
final imgTag = document.querySelector('img');
|
||||||
|
expect(imgTag?.attributes['src'], 'cid:test123');
|
||||||
|
expect(imgTag?.attributes.containsKey('id'), isFalse);
|
||||||
|
expect(result.value2.length, 1);
|
||||||
|
expect(result.value2.first.cid, 'test123');
|
||||||
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'When HTML content has a base64 image and upload succeeds,\n'
|
'When HTML content has a base64 image and upload succeeds,\n'
|
||||||
'should replace src with new CID and add attachment to result',
|
'should replace src with new CID and add attachment to result',
|
||||||
@@ -101,6 +132,7 @@ void main() {
|
|||||||
expect(imgTag?.attributes['src'], 'cid:new-uuid-123');
|
expect(imgTag?.attributes['src'], 'cid:new-uuid-123');
|
||||||
expect(result.value2.length, 1);
|
expect(result.value2.length, 1);
|
||||||
expect(result.value2.first.cid, 'new-uuid-123');
|
expect(result.value2.first.cid, 'new-uuid-123');
|
||||||
|
verify(mockUuid.v1()).called(1);
|
||||||
verify(mockFileUploader.uploadAttachment(any, any, uploadUri)).called(1);
|
verify(mockFileUploader.uploadAttachment(any, any, uploadUri)).called(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -151,9 +183,10 @@ void main() {
|
|||||||
final document = parse(result.value1);
|
final document = parse(result.value1);
|
||||||
final imgTags = document.querySelectorAll('img');
|
final imgTags = document.querySelectorAll('img');
|
||||||
expect(imgTags.length, 2);
|
expect(imgTags.length, 2);
|
||||||
expect(imgTags[0].attributes['src'], 'cid:uuid1');
|
expect(imgTags[0].attributes['src'], contains('cid:'));
|
||||||
expect(imgTags[1].attributes['src'], 'cid:uuid1');
|
expect(imgTags[1].attributes['src'], contains('cid:'));
|
||||||
expect(result.value2.length, 2);
|
expect(result.value2.length, 2);
|
||||||
|
verify(mockUuid.v1()).called(2);
|
||||||
verify(mockFileUploader.uploadAttachment(any, any, uploadUri)).called(2);
|
verify(mockFileUploader.uploadAttachment(any, any, uploadUri)).called(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -198,6 +231,7 @@ void main() {
|
|||||||
expect(imgTags[1].attributes['src'], 'data:image/jpeg;base64,/9j/4AAQSkZJRg==');
|
expect(imgTags[1].attributes['src'], 'data:image/jpeg;base64,/9j/4AAQSkZJRg==');
|
||||||
expect(result.value2.length, 1);
|
expect(result.value2.length, 1);
|
||||||
expect(result.value2.first.cid, 'uuid1');
|
expect(result.value2.first.cid, 'uuid1');
|
||||||
|
verify(mockUuid.v1()).called(2);
|
||||||
verify(mockFileUploader.uploadAttachment(any, any, uploadUri)).called(2);
|
verify(mockFileUploader.uploadAttachment(any, any, uploadUri)).called(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -229,6 +263,7 @@ void main() {
|
|||||||
expect(imgTags[0].attributes['src'], 'data:image/png;base64,iVBORw0KGgo=');
|
expect(imgTags[0].attributes['src'], 'data:image/png;base64,iVBORw0KGgo=');
|
||||||
expect(imgTags[1].attributes['src'], 'data:image/jpeg;base64,/9j/4AAQSkZJRg==');
|
expect(imgTags[1].attributes['src'], 'data:image/jpeg;base64,/9j/4AAQSkZJRg==');
|
||||||
expect(result.value2.length, 0);
|
expect(result.value2.length, 0);
|
||||||
|
verify(mockUuid.v1()).called(2);
|
||||||
verify(mockFileUploader.uploadAttachment(any, any, uploadUri)).called(2);
|
verify(mockFileUploader.uploadAttachment(any, any, uploadUri)).called(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -256,6 +291,7 @@ void main() {
|
|||||||
expect(imgTags.length, 1);
|
expect(imgTags.length, 1);
|
||||||
expect(imgTags[0].attributes['src'], 'data:image/png;base64,invalid-base64-data');
|
expect(imgTags[0].attributes['src'], 'data:image/png;base64,invalid-base64-data');
|
||||||
expect(result.value2.length, 0);
|
expect(result.value2.length, 0);
|
||||||
|
verify(mockUuid.v1()).called(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
@@ -282,6 +318,7 @@ void main() {
|
|||||||
expect(imgTags.length, 1);
|
expect(imgTags.length, 1);
|
||||||
expect(imgTags[0].attributes['src'], 'data:image/png;base64,iVBORw0KGgo=');
|
expect(imgTags[0].attributes['src'], 'data:image/png;base64,iVBORw0KGgo=');
|
||||||
expect(result.value2.length, 0);
|
expect(result.value2.length, 0);
|
||||||
|
verify(mockUuid.v1()).called(1);
|
||||||
verify(mockFileUploader.uploadAttachment(any, any, any)).called(1);
|
verify(mockFileUploader.uploadAttachment(any, any, any)).called(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user