import 'package:flutter_test/flutter_test.dart'; import 'package:ikar/backend/modules/chat_preview.dart'; import 'package:ikar/models/chat_preview_media.dart'; const String _thumbA = 'data:image/webp;base64,AAAA'; const String _thumbB = 'data:image/webp;base64,BBBB'; const String _thumbC = 'data:image/webp;base64,CCCC'; const String _thumbD = 'data:image/webp;base64,DDDD'; Map _photo(String preview) => { '_type': 'PHOTO', 'previewData': preview, 'photoId': 1, }; Map _video(String preview) => { '_type': 'VIDEO', 'previewData': preview, 'videoId': 2, }; ChatPreviewMedia _media(Map msg) { final encoded = messagePreviewMedia(msg); expect(encoded, isNotNull); final decoded = ChatPreviewMedia.decode(encoded); expect(decoded, isNotNull); return decoded!; } void main() { group('превью вложений', () { test('одиночное фото без подписи даёт миниатюру и словесную подпись', () { final msg = { 'text': '', 'attaches': [_photo(_thumbA)], }; final media = _media(msg); expect(media.kind, ChatPreviewKind.photo); expect(media.captioned, isFalse); expect(media.label, 'Изображение'); expect(media.detail, isNull); expect(media.thumbs.map((t) => t.source), [_thumbA]); expect(media.thumbs.single.video, isFalse); expect(messagePreviewText(msg), 'Изображение'); }); test('фото с подписью оставляет текст сообщения', () { final msg = { 'text': 'подпись', 'attaches': [_photo(_thumbA)], }; final media = _media(msg); expect(media.captioned, isTrue); expect(media.label, isNull); expect(media.thumbs, hasLength(1)); expect(messagePreviewText(msg), 'подпись'); }); test('альбом отдаёт не больше трёх миниатюр и помечает видео', () { final msg = { 'text': '', 'attaches': [ _photo(_thumbA), _video(_thumbB), _photo(_thumbC), _photo(_thumbD), ], }; final media = _media(msg); expect(media.label, 'Изображения'); expect(media.thumbs.map((t) => t.source), [_thumbA, _thumbB, _thumbC]); expect(media.thumbs.map((t) => t.video), [false, true, false]); }); test('кружок не считается обычным видео', () { final msg = { 'text': '', 'attaches': [ {'_type': 'VIDEO', 'videoType': 1, 'previewData': _thumbA}, ], }; final media = _media(msg); expect(media.kind, ChatPreviewKind.videoNote); expect(media.label, 'Видео-сообщение'); }); test('файл отдаёт имя отдельно от подписи', () { final msg = { 'text': '', 'attaches': [ {'_type': 'FILE', 'name': 'notes.pdf', 'fileId': 3}, ], }; final media = _media(msg); expect(media.kind, ChatPreviewKind.file); expect(media.label, 'Файл'); expect(media.detail, 'notes.pdf'); expect(media.thumbs, isEmpty); expect(messagePreviewText(msg), 'Файл: notes.pdf'); }); test('пропущенный звонок отличается от состоявшегося', () { final missed = _media({ 'text': '', 'attaches': [ {'_type': 'CALL', 'callType': 'AUDIO', 'duration': 0}, ], }); expect(missed.kind, ChatPreviewKind.missedCall); expect(missed.label, 'Пропущенный звонок'); final answered = _media({ 'text': '', 'attaches': [ {'_type': 'CALL', 'callType': 'VIDEO', 'duration': 42}, ], }); expect(answered.kind, ChatPreviewKind.videoCall); expect(answered.label, 'Видеозвонок'); }); test('пересланное вложение сохраняет метку пересылки', () { final msg = { 'text': '', 'link': { 'type': 'FORWARD', 'message': { 'text': '', 'attaches': [_photo(_thumbA)], }, }, }; final media = _media(msg); expect(media.kind, ChatPreviewKind.photo); expect(media.label, '↪ Изображение'); expect(media.thumbs, hasLength(1)); expect(messagePreviewText(msg), '↪ Изображение'); }); test('клавиатура бота не считается вложением', () { final encoded = messagePreviewMedia({ 'text': 'выбери вариант', 'attaches': [ {'_type': 'INLINE_KEYBOARD'}, ], }); expect(encoded, isNull); }); test('без вложений описания нет', () { expect(messagePreviewMedia({'text': 'привет'}), isNull); }); test('слишком тяжёлая миниатюра не попадает в кеш чатов', () { final heavy = 'data:image/webp;base64,${'A' * 30000}'; final media = _media({ 'text': '', 'attaches': [_photo(heavy)], }); expect(media.thumbs, isEmpty); }); test('описание переживает сериализацию', () { const media = ChatPreviewMedia( kind: ChatPreviewKind.video, thumbs: [ ChatPreviewThumb(source: _thumbA, video: true), ChatPreviewThumb(source: _thumbB), ], label: 'Видео', ); final restored = ChatPreviewMedia.decode(media.encode())!; expect(restored.kind, ChatPreviewKind.video); expect(restored.label, 'Видео'); expect(restored.detail, isNull); expect(restored.thumbs.map((t) => t.source), [_thumbA, _thumbB]); expect(restored.thumbs.map((t) => t.video), [true, false]); }); test('битое описание не роняет разбор', () { expect(ChatPreviewMedia.decode('{'), isNull); expect(ChatPreviewMedia.decode('{"k":"чтоэто"}'), isNull); expect(ChatPreviewMedia.decode(null), isNull); }); }); }