diff --git a/core/lib/presentation/utils/html_transformer/sanitize_autolink_filter.dart b/core/lib/presentation/utils/html_transformer/sanitize_autolink_filter.dart
index 92ab8c2e5..1dcad41e1 100644
--- a/core/lib/presentation/utils/html_transformer/sanitize_autolink_filter.dart
+++ b/core/lib/presentation/utils/html_transformer/sanitize_autolink_filter.dart
@@ -7,6 +7,7 @@ import 'package:linkify/linkify.dart';
class SanitizeAutolinkFilter {
final HtmlEscape htmlEscape;
+ final bool escapeHtml;
final _linkifyOption = const LinkifyOptions(
humanize: true,
looseUrl: true,
@@ -18,7 +19,7 @@ class SanitizeAutolinkFilter {
const UrlLinkifier()
];
- SanitizeAutolinkFilter(this.htmlEscape);
+ SanitizeAutolinkFilter(this.htmlEscape, {this.escapeHtml = true});
String process(String inputText) {
try {
@@ -36,7 +37,7 @@ class SanitizeAutolinkFilter {
for (var element in elements) {
if (element is TextElement) {
- final escapedHtml = htmlEscape.convert(element.text);
+ final escapedHtml = escapeHtml ? htmlEscape.convert(element.text) : element.text;
htmlTextBuffer.write(escapedHtml);
} else if (element is EmailElement) {
final emailLinkTag = _buildEmailLinkTag(
diff --git a/core/lib/presentation/utils/html_transformer/text/new_line_transformer.dart b/core/lib/presentation/utils/html_transformer/text/new_line_transformer.dart
new file mode 100644
index 000000000..4b13b7646
--- /dev/null
+++ b/core/lib/presentation/utils/html_transformer/text/new_line_transformer.dart
@@ -0,0 +1,15 @@
+import 'dart:convert';
+
+import 'package:core/presentation/utils/html_transformer/base/text_transformer.dart';
+
+class NewLineTransformer extends TextTransformer {
+ const NewLineTransformer();
+
+ @override
+ String process(String text, HtmlEscape htmlEscape) {
+ return text
+ .replaceAll('\n', '
')
+ .replaceAll('\r', ' ')
+ .replaceAll('\t', ' ');
+ }
+}
\ No newline at end of file
diff --git a/core/lib/presentation/utils/html_transformer/text/sanitize_autolink_unescape_html_transformer.dart b/core/lib/presentation/utils/html_transformer/text/sanitize_autolink_unescape_html_transformer.dart
new file mode 100644
index 000000000..75aba0085
--- /dev/null
+++ b/core/lib/presentation/utils/html_transformer/text/sanitize_autolink_unescape_html_transformer.dart
@@ -0,0 +1,13 @@
+import 'dart:convert';
+
+import 'package:core/presentation/utils/html_transformer/base/text_transformer.dart';
+import 'package:core/presentation/utils/html_transformer/sanitize_autolink_filter.dart';
+
+class SanitizeAutolinkUnescapeHtmlTransformer extends TextTransformer {
+ const SanitizeAutolinkUnescapeHtmlTransformer();
+
+ @override
+ String process(String text, HtmlEscape htmlEscape) {
+ return SanitizeAutolinkFilter(htmlEscape, escapeHtml: false).process(text);
+ }
+}
\ No newline at end of file
diff --git a/lib/features/email/data/repository/calendar_event_repository_impl.dart b/lib/features/email/data/repository/calendar_event_repository_impl.dart
index 49c59dce7..c0e48e417 100644
--- a/lib/features/email/data/repository/calendar_event_repository_impl.dart
+++ b/lib/features/email/data/repository/calendar_event_repository_impl.dart
@@ -1,19 +1,24 @@
import 'package:core/data/model/source_type/data_source_type.dart';
+import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_accept_response.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_maybe_response.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_reject_response.dart';
import 'package:tmail_ui_user/features/email/data/datasource/calendar_event_datasource.dart';
+import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dart';
import 'package:tmail_ui_user/features/email/domain/repository/calendar_event_repository.dart';
+import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_event_extension.dart';
import 'package:tmail_ui_user/features/email/presentation/model/blob_calendar_event.dart';
class CalendarEventRepositoryImpl extends CalendarEventRepository {
final Map _calendarEventDataSource;
+ final HtmlDataSource _htmlDataSource;
- CalendarEventRepositoryImpl(this._calendarEventDataSource);
+ CalendarEventRepositoryImpl(this._calendarEventDataSource, this._htmlDataSource);
@override
Future> parse(AccountId accountId, Set blobIds) {
@@ -49,4 +54,33 @@ class CalendarEventRepositoryImpl extends CalendarEventRepository {
return _calendarEventDataSource[DataSourceType.network]!
.rejectEventInvitation(accountId, blobIds, language);
}
+
+ @override
+ Future> transformCalendarEventDescription(
+ List blobCalendarEvents,
+ TransformConfiguration transformConfiguration,
+ ) async {
+ return Future.wait(blobCalendarEvents.map((blobCalendarEvent) async {
+ return BlobCalendarEvent(
+ blobId: blobCalendarEvent.blobId,
+ calendarEventList: await Future.wait(blobCalendarEvent.calendarEventList.map((calendarEvent) {
+ return _transformCalendarEventDescription(calendarEvent, transformConfiguration);
+ })),
+ );
+ }));
+ }
+
+ Future _transformCalendarEventDescription(
+ CalendarEvent calendarEvent,
+ TransformConfiguration transformConfiguration,
+ ) async {
+ return calendarEvent.copyWith(
+ description: calendarEvent.description?.trim().isNotEmpty == true
+ ? await _htmlDataSource.transformHtmlEmailContent(
+ calendarEvent.description!,
+ transformConfiguration,
+ )
+ : calendarEvent.description,
+ );
+ }
}
\ No newline at end of file
diff --git a/lib/features/email/domain/repository/calendar_event_repository.dart b/lib/features/email/domain/repository/calendar_event_repository.dart
index de287e0e4..cf2f19318 100644
--- a/lib/features/email/domain/repository/calendar_event_repository.dart
+++ b/lib/features/email/domain/repository/calendar_event_repository.dart
@@ -1,4 +1,5 @@
+import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_accept_response.dart';
@@ -23,4 +24,8 @@ abstract class CalendarEventRepository {
AccountId accountId,
Set blobIds,
String? language);
+
+ Future> transformCalendarEventDescription(
+ List blobCalendarEvents,
+ TransformConfiguration transformConfiguration);
}
\ No newline at end of file
diff --git a/lib/features/email/domain/usecases/parse_calendar_event_interactor.dart b/lib/features/email/domain/usecases/parse_calendar_event_interactor.dart
index 55b11e5fb..f7ceff884 100644
--- a/lib/features/email/domain/usecases/parse_calendar_event_interactor.dart
+++ b/lib/features/email/domain/usecases/parse_calendar_event_interactor.dart
@@ -1,5 +1,6 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
+import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
@@ -15,15 +16,19 @@ class ParseCalendarEventInteractor {
Stream> execute(
AccountId accountId,
Set blobIds,
- String emailContents
+ TransformConfiguration transformConfiguration,
) async* {
try {
yield Right(ParseCalendarEventLoading());
final listBlobCalendarEvent = await _calendarEventRepository.parse(accountId, blobIds);
+ final listBlobCalendarEventWithTransformedDescription = await _calendarEventRepository.transformCalendarEventDescription(
+ listBlobCalendarEvent,
+ transformConfiguration,
+ );
- if (listBlobCalendarEvent.isNotEmpty) {
- yield Right(ParseCalendarEventSuccess(listBlobCalendarEvent));
+ if (listBlobCalendarEventWithTransformedDescription.isNotEmpty) {
+ yield Right(ParseCalendarEventSuccess(listBlobCalendarEventWithTransformedDescription));
} else {
yield Left(ParseCalendarEventFailure(NotFoundCalendarEventException()));
}
diff --git a/lib/features/email/presentation/bindings/calendar_event_interactor_bindings.dart b/lib/features/email/presentation/bindings/calendar_event_interactor_bindings.dart
index e4718ed82..7d841f8ea 100644
--- a/lib/features/email/presentation/bindings/calendar_event_interactor_bindings.dart
+++ b/lib/features/email/presentation/bindings/calendar_event_interactor_bindings.dart
@@ -3,7 +3,10 @@ import 'package:get/get.dart';
import 'package:jmap_dart_client/http/http_client.dart';
import 'package:tmail_ui_user/features/base/interactors_bindings.dart';
import 'package:tmail_ui_user/features/email/data/datasource/calendar_event_datasource.dart';
+import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dart';
import 'package:tmail_ui_user/features/email/data/datasource_impl/calendar_event_datasource_impl.dart';
+import 'package:tmail_ui_user/features/email/data/datasource_impl/html_datasource_impl.dart';
+import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
import 'package:tmail_ui_user/features/email/data/network/calendar_event_api.dart';
import 'package:tmail_ui_user/features/email/data/repository/calendar_event_repository_impl.dart';
import 'package:tmail_ui_user/features/email/domain/repository/calendar_event_repository.dart';
@@ -11,6 +14,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_acce
import 'package:tmail_ui_user/features/email/domain/usecases/maybe_calendar_event_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_reject_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/parse_calendar_event_interactor.dart';
+import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
class CalendarEventInteractorBindings extends InteractorsBindings {
@@ -18,6 +22,7 @@ class CalendarEventInteractorBindings extends InteractorsBindings {
@override
void bindingsDataSource() {
Get.lazyPut(() => Get.find());
+ Get.lazyPut(() => Get.find());
}
@override
@@ -26,6 +31,9 @@ class CalendarEventInteractorBindings extends InteractorsBindings {
Get.lazyPut(() => CalendarEventDataSourceImpl(
Get.find(),
Get.find()));
+ Get.lazyPut(() => HtmlDataSourceImpl(
+ Get.find(),
+ Get.find()));
}
@override
@@ -44,7 +52,8 @@ class CalendarEventInteractorBindings extends InteractorsBindings {
@override
void bindingsRepositoryImpl() {
Get.lazyPut(() => CalendarEventRepositoryImpl(
- {DataSourceType.network: Get.find()}
+ {DataSourceType.network: Get.find()},
+ Get.find(),
));
}
}
\ No newline at end of file
diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart
index e40e78fca..45449b497 100644
--- a/lib/features/email/presentation/controller/single_email_controller.dart
+++ b/lib/features/email/presentation/controller/single_email_controller.dart
@@ -4,6 +4,9 @@ import 'dart:typed_data';
import 'package:better_open_file/better_open_file.dart' as open_file;
import 'package:core/core.dart';
+import 'package:core/presentation/utils/html_transformer/text/sanitize_autolink_unescape_html_transformer.dart';
+import 'package:core/presentation/utils/html_transformer/text/new_line_transformer.dart';
+import 'package:core/presentation/utils/html_transformer/text/standardize_html_sanitizing_transformers.dart';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
@@ -519,7 +522,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
_parseCalendarEventAction(
accountId: mailboxDashBoardController.accountId.value!,
blobIds: success.attachments?.calendarEventBlobIds ?? {},
- emailContents: success.htmlEmailContent
);
} else {
emailContents.value = success.htmlEmailContent;
@@ -564,7 +566,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
_parseCalendarEventAction(
accountId: mailboxDashBoardController.accountId.value!,
blobIds: success.attachments?.calendarEventBlobIds ?? {},
- emailContents: success.htmlEmailContent
);
} else {
emailContents.value = success.htmlEmailContent;
@@ -1466,13 +1467,26 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
CapabilityIdentifier.jamesCalendarEvent.isSupported(session, accountId);
}
+ @visibleForTesting
+ parseCalendarEventAction({
+ required AccountId accountId,
+ required Set blobIds,
+ }) => _parseCalendarEventAction(accountId: accountId, blobIds: blobIds);
+
void _parseCalendarEventAction({
required AccountId accountId,
required Set blobIds,
- required String emailContents
}) {
log("SingleEmailController::_parseCalendarEventAction:blobIds: $blobIds");
- consumeState(_parseCalendarEventInteractor!.execute(accountId, blobIds, emailContents));
+ consumeState(_parseCalendarEventInteractor!.execute(
+ accountId,
+ blobIds,
+ TransformConfiguration.fromTextTransformers(const [
+ SanitizeAutolinkUnescapeHtmlTransformer(),
+ StandardizeHtmlSanitizingTransformers(),
+ NewLineTransformer(),
+ ])
+ ));
}
void _handleParseCalendarEventSuccess(ParseCalendarEventSuccess success) {
diff --git a/lib/features/email/presentation/extensions/calendar_event_extension.dart b/lib/features/email/presentation/extensions/calendar_event_extension.dart
index 2a7c895e0..f993c87cb 100644
--- a/lib/features/email/presentation/extensions/calendar_event_extension.dart
+++ b/lib/features/email/presentation/extensions/calendar_event_extension.dart
@@ -5,10 +5,21 @@ import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/utils/app_logger.dart';
import 'package:date_format/date_format.dart' as date_format;
import 'package:flutter/material.dart';
+import 'package:jmap_dart_client/jmap/core/utc_date.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/properties/attendee/calendar_attendee.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/properties/attendee/calendar_attendee_participation_status.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_duration.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_event_status.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_extension_fields.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_free_busy_status.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_organizer.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_priority.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_privacy.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/calendar_sequence.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_id.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_method.dart';
+import 'package:jmap_dart_client/jmap/mail/calendar/properties/recurrence_rule/recurrence_rule.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/utils/app_utils.dart';
@@ -364,4 +375,52 @@ extension CalendarEventExtension on CalendarEvent {
method == EventMethod.request ||
method == EventMethod.add ||
method == EventMethod.counter;
+
+ CalendarEvent copyWith({
+ EventId? eventId,
+ String? title,
+ String? description,
+ DateTime? startDate,
+ DateTime? endDate,
+ UTCDate? startUtcDate,
+ UTCDate? endUtcDate,
+ CalendarDuration? duration,
+ String? timeZone,
+ String? location,
+ EventMethod? method,
+ CalendarSequence? sequence,
+ CalendarPrivacy? privacy,
+ CalendarPriority? priority,
+ CalendarFreeBusyStatus? freeBusyStatus,
+ CalendarEventStatus? status,
+ CalendarOrganizer? organizer,
+ List? participants,
+ CalendarExtensionFields? extensionFields,
+ List? recurrenceRules,
+ List? excludedCalendarEvents,
+ }) {
+ return CalendarEvent(
+ eventId: eventId ?? this.eventId,
+ title: title ?? this.title,
+ description: description ?? this.description,
+ startDate: startDate ?? this.startDate,
+ endDate: endDate ?? this.endDate,
+ startUtcDate: startUtcDate ?? this.startUtcDate,
+ endUtcDate: endUtcDate ?? this.endUtcDate,
+ duration: duration ?? this.duration,
+ timeZone: timeZone ?? this.timeZone,
+ location: location ?? this.location,
+ method: method ?? this.method,
+ sequence: sequence ?? this.sequence,
+ privacy: privacy ?? this.privacy,
+ priority: priority ?? this.priority,
+ freeBusyStatus: freeBusyStatus ?? this.freeBusyStatus,
+ status: status ?? this.status,
+ organizer: organizer ?? this.organizer,
+ participants: participants ?? this.participants,
+ extensionFields: extensionFields ?? this.extensionFields,
+ recurrenceRules: recurrenceRules ?? this.recurrenceRules,
+ excludedCalendarEvents: excludedCalendarEvents ?? this.excludedCalendarEvents,
+ );
+ }
}
\ No newline at end of file
diff --git a/test/features/email/data/repository/calendar_event_repository_impl_test.dart b/test/features/email/data/repository/calendar_event_repository_impl_test.dart
index 43b51824a..67c4bc3d7 100644
--- a/test/features/email/data/repository/calendar_event_repository_impl_test.dart
+++ b/test/features/email/data/repository/calendar_event_repository_impl_test.dart
@@ -9,17 +9,25 @@ import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_reject_
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:tmail_ui_user/features/email/data/datasource/calendar_event_datasource.dart';
+import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dart';
import 'package:tmail_ui_user/features/email/data/repository/calendar_event_repository_impl.dart';
import 'package:tmail_ui_user/features/email/domain/exceptions/calendar_event_exceptions.dart';
import 'calendar_event_repository_impl_test.mocks.dart';
-@GenerateNiceMocks([MockSpec()])
+@GenerateNiceMocks([
+ MockSpec(),
+ MockSpec(),
+])
void main() {
final calendarEventNetworkDataSource = MockCalendarEventDataSource();
+ final htmlDatasource = MockHtmlDataSource();
final calendarEventDataSource = {
DataSourceType.network: calendarEventNetworkDataSource};
- final calendarEventRepository = CalendarEventRepositoryImpl(calendarEventDataSource);
+ final calendarEventRepository = CalendarEventRepositoryImpl(
+ calendarEventDataSource,
+ htmlDatasource,
+ );
final accountId = AccountId(Id('123'));
final blobId = Id('blobId');
const language = 'en';
diff --git a/test/features/email/presentation/controller/single_email_controller_test.dart b/test/features/email/presentation/controller/single_email_controller_test.dart
index 1768bc934..9ba67d1e3 100644
--- a/test/features/email/presentation/controller/single_email_controller_test.dart
+++ b/test/features/email/presentation/controller/single_email_controller_test.dart
@@ -1,3 +1,4 @@
+import 'dart:convert';
import 'dart:ui';
import 'package:core/core.dart';
@@ -18,7 +19,12 @@ import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_accept_
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
+import 'package:model/email/presentation_email.dart';
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
+import 'package:tmail_ui_user/features/email/data/datasource/calendar_event_datasource.dart';
+import 'package:tmail_ui_user/features/email/data/datasource_impl/html_datasource_impl.dart';
+import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
+import 'package:tmail_ui_user/features/email/data/repository/calendar_event_repository_impl.dart';
import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
import 'package:tmail_ui_user/features/email/domain/state/calendar_event_accept_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart';
@@ -32,9 +38,11 @@ import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_i
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
+import 'package:tmail_ui_user/features/email/domain/usecases/parse_calendar_event_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/print_email_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/store_event_attendance_status_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/store_opened_email_interactor.dart';
+import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart';
import 'package:tmail_ui_user/features/email/presentation/controller/email_supervisor_controller.dart';
import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart';
import 'package:tmail_ui_user/features/email/presentation/model/blob_calendar_event.dart';
@@ -46,9 +54,11 @@ import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_
import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart';
import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart';
+import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
import 'package:tmail_ui_user/main/utils/toast_manager.dart';
import 'package:uuid/uuid.dart';
+import '../../../../fixtures/account_fixtures.dart';
import '../../../../fixtures/email_fixtures.dart';
import 'single_email_controller_test.mocks.dart';
@@ -91,6 +101,8 @@ const fallbackGenerators = {
MockSpec(),
MockSpec(),
MockSpec(),
+ MockSpec(),
+ MockSpec(),
])
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
@@ -363,4 +375,137 @@ void main() {
debugDefaultTargetPlatformOverride = null;
});
});
+
+ group('_parseCalendarEventAction method test:', () {
+ final calendarEventDataSource = MockCalendarEventDataSource();
+ final calendarEventRepository = CalendarEventRepositoryImpl(
+ {DataSourceType.network :calendarEventDataSource},
+ HtmlDataSourceImpl(
+ HtmlAnalyzer(HtmlTransform(
+ MockDioClient(),
+ const HtmlEscape(),
+ )),
+ CacheExceptionThrower(),
+ ),
+ );
+
+ setUp(() {
+ Get.put(ParseCalendarEventInteractor(calendarEventRepository));
+ });
+
+ tearDown(() {
+ Get.delete();
+ });
+
+ test(
+ 'should transform all calendar event description url to a tag '
+ 'and all new line to
tag',
+ () async {
+ // arrange
+ const eventDescription = '\nhttps://example1.com\nhttps://example2.com';
+ const expectedEventDescription = ''
+ '
'
+ 'example1.com'
+ '
'
+ 'example2.com'
+ '';
+ final blobId = Id('abc123');
+ final calendarEvent = CalendarEvent(
+ description: eventDescription,
+ );
+ final blobCalendarEvents = [
+ BlobCalendarEvent(
+ blobId: blobId,
+ calendarEventList: [calendarEvent],
+ ),
+ ];
+ when(calendarEventDataSource.parse(any, any))
+ .thenAnswer((_) async => blobCalendarEvents);
+
+ when(mailboxDashboardController.selectedEmail).thenReturn(Rxn(PresentationEmail()));
+ when(mailboxDashboardController.emailUIAction).thenReturn(Rxn(EmailUIAction()));
+ when(mailboxDashboardController.viewState).thenReturn(Rx(Right(UIState.idle)));
+ when(mailboxDashboardController.accountId).thenReturn(Rxn(AccountFixtures.aliceAccountId));
+ when(emailSupervisorController.scrollPhysicsPageView).thenReturn(Rxn());
+
+ singleEmailController.onInit();
+ mailboxDashboardController.accountId.refresh();
+
+ // act
+ singleEmailController.parseCalendarEventAction(
+ accountId: AccountFixtures.aliceAccountId,
+ blobIds: {blobId},
+ );
+ await untilCalled(calendarEventDataSource.parse(any, any));
+ await Future.delayed(Duration.zero);
+
+ // assert
+ expect(
+ singleEmailController.blobCalendarEvent.value,
+ BlobCalendarEvent(
+ blobId: blobId,
+ calendarEventList: [CalendarEvent(description: expectedEventDescription)],
+ ),
+ );
+ });
+
+ test(
+ 'should transform all calendar event description url to a tag '
+ 'and all new line to
tag '
+ 'and remove all xss attempt',
+ () async {
+ // arrange
+ const eventDescription = '\nhttps://example1.com'
+ '\nhttps://example2.com'
+ '\n'
+ '\nhref xss';
+ const expectedEventDescription = ''
+ '
'
+ 'example1.com'
+ '
'
+ 'example2.com'
+ '
'
+ '
'
+ 'href xss'
+ '';
+ final blobId = Id('abc123');
+ final calendarEvent = CalendarEvent(
+ description: eventDescription,
+ );
+ final blobCalendarEvents = [
+ BlobCalendarEvent(
+ blobId: blobId,
+ calendarEventList: [calendarEvent],
+ ),
+ ];
+ when(calendarEventDataSource.parse(any, any))
+ .thenAnswer((_) async => blobCalendarEvents);
+
+ when(mailboxDashboardController.selectedEmail).thenReturn(Rxn(PresentationEmail()));
+ when(mailboxDashboardController.emailUIAction).thenReturn(Rxn(EmailUIAction()));
+ when(mailboxDashboardController.viewState).thenReturn(Rx(Right(UIState.idle)));
+ when(mailboxDashboardController.accountId).thenReturn(Rxn(AccountFixtures.aliceAccountId));
+ when(emailSupervisorController.scrollPhysicsPageView).thenReturn(Rxn());
+
+ singleEmailController.onInit();
+ mailboxDashboardController.accountId.refresh();
+
+ // act
+ singleEmailController.parseCalendarEventAction(
+ accountId: AccountFixtures.aliceAccountId,
+ blobIds: {blobId},
+ );
+ await untilCalled(calendarEventDataSource.parse(any, any));
+ await Future.delayed(Duration.zero);
+
+ // assert
+ expect(
+ singleEmailController.blobCalendarEvent.value,
+ BlobCalendarEvent(
+ blobId: blobId,
+ calendarEventList: [CalendarEvent(description: expectedEventDescription)],
+ ),
+ );
+ });
+ });
}