diff --git a/lib/features/base/mixin/date_range_picker_mixin.dart b/lib/features/base/mixin/date_range_picker_mixin.dart index 10f746f81..70ad1744f 100644 --- a/lib/features/base/mixin/date_range_picker_mixin.dart +++ b/lib/features/base/mixin/date_range_picker_mixin.dart @@ -22,7 +22,7 @@ mixin DateRangePickerMixin { last7daysTitle: AppLocalizations.of(context).last7Days, last30daysTitle: AppLocalizations.of(context).last30Days, last6monthsTitle: AppLocalizations.of(context).last6Months, - lastYearTitle: AppLocalizations.of(context).lastYears, + lastYearTitle: AppLocalizations.of(context).last1Year, initStartDate: initStartDate, initEndDate: initEndDate, autoClose: false, diff --git a/lib/features/email_recovery/presentation/email_recovery_controller.dart b/lib/features/email_recovery/presentation/email_recovery_controller.dart index 61da363e4..b93a04d64 100644 --- a/lib/features/email_recovery/presentation/email_recovery_controller.dart +++ b/lib/features/email_recovery/presentation/email_recovery_controller.dart @@ -8,9 +8,7 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/utc_date.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; -import 'package:model/autocomplete/auto_complete_pattern.dart'; -import 'package:model/extensions/email_address_extension.dart'; -import 'package:model/mailbox/expand_mode.dart'; +import 'package:model/model.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:super_tag_editor/tag_editor.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; @@ -25,6 +23,7 @@ import 'package:tmail_ui_user/features/email_recovery/presentation/controller/in import 'package:tmail_ui_user/features/email_recovery/presentation/model/email_recovery_arguments.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/model/email_recovery_field.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/model/email_recovery_time_type.dart'; +import 'package:tmail_ui_user/features/email_recovery/presentation/model/session_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/extensions/datetime_extension.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/utils/app_config.dart'; @@ -34,7 +33,7 @@ class EmailRecoveryController extends BaseController with DateRangePickerMixin { GetAutoCompleteInteractor? _getAutoCompleteInteractor; GetDeviceContactSuggestionsInteractor? _getDeviceContactSuggestionsInteractor; - final deletionDateFieldSelected = EmailRecoveryTimeType.last1Year.obs; + final deletionDateFieldSelected = EmailRecoveryTimeType.last7Days.obs; final receptionDateFieldSelected = EmailRecoveryTimeType.allTime.obs; final startDeletionDate = Rxn(); final endDeletionDate = Rxn(); @@ -354,6 +353,10 @@ class EmailRecoveryController extends BaseController with DateRangePickerMixin { popBack(); } + String getRestorationHorizonAsString() => arguments!.session.getRestorationHorizonAsString(); + + DateTime getRestorationHorizonAsDateTime() => arguments!.session.getRestorationHorizonAsDateTime(); + @override void dispose() { focusManager.subjectFieldFocusNode.removeListener(_onSubjectFieldFocusChanged); diff --git a/lib/features/email_recovery/presentation/model/email_recovery_field.dart b/lib/features/email_recovery/presentation/model/email_recovery_field.dart index fb98b1156..522942eba 100644 --- a/lib/features/email_recovery/presentation/model/email_recovery_field.dart +++ b/lib/features/email_recovery/presentation/model/email_recovery_field.dart @@ -28,7 +28,7 @@ enum EmailRecoveryField { String getHintText(BuildContext context) { switch (this) { case EmailRecoveryField.deletionDate: - return AppLocalizations.of(context).last1Year; + return AppLocalizations.of(context).last7Days; case EmailRecoveryField.receptionDate: return AppLocalizations.of(context).allTime; case EmailRecoveryField.subject: @@ -40,16 +40,20 @@ enum EmailRecoveryField { } } - List getSupportedTimeTypes() { + List getSupportedTimeTypes(DateTime restorationHorizon) { switch (this) { case EmailRecoveryField.deletionDate: - return [ - EmailRecoveryTimeType.last1Year, + final supportedTypes = [ EmailRecoveryTimeType.last7Days, + EmailRecoveryTimeType.last15Days, EmailRecoveryTimeType.last30Days, EmailRecoveryTimeType.last6Months, - EmailRecoveryTimeType.customRange, - ]; + EmailRecoveryTimeType.last1Year, + ].where((type) => restorationHorizon + .subtract(const Duration(seconds: 2)) // to allow "15 days" if restorationHorizon is exactly 15 + .isBefore(type.toOldestUTCDate()!.value)).toList(); + + return [...supportedTypes, EmailRecoveryTimeType.customRange]; case EmailRecoveryField.receptionDate: return [ EmailRecoveryTimeType.allTime, diff --git a/lib/features/email_recovery/presentation/model/email_recovery_time_type.dart b/lib/features/email_recovery/presentation/model/email_recovery_time_type.dart index a9f553100..632da6bb2 100644 --- a/lib/features/email_recovery/presentation/model/email_recovery_time_type.dart +++ b/lib/features/email_recovery/presentation/model/email_recovery_time_type.dart @@ -6,6 +6,7 @@ import 'package:jmap_dart_client/jmap/core/utc_date.dart'; enum EmailRecoveryTimeType { allTime, last7Days, + last15Days, last30Days, last6Months, last1Year, @@ -18,6 +19,8 @@ enum EmailRecoveryTimeType { return AppLocalizations.of(context).allTime; case EmailRecoveryTimeType.last7Days: return AppLocalizations.of(context).last7Days; + case EmailRecoveryTimeType.last15Days: + return AppLocalizations.of(context).last15Days; case EmailRecoveryTimeType.last30Days: return AppLocalizations.of(context).last30Days; case EmailRecoveryTimeType.last6Months: @@ -47,6 +50,10 @@ enum EmailRecoveryTimeType { final today = DateTime.now(); final last7Days = today.subtract(const Duration(days: 7)); return last7Days.toUTCDate(); + case EmailRecoveryTimeType.last15Days: + final today = DateTime.now(); + final last15Days = today.subtract(const Duration(days: 15)); + return last15Days.toUTCDate(); case EmailRecoveryTimeType.last30Days: final today = DateTime.now(); final last30Days = today.subtract(const Duration(days: 30)); @@ -68,6 +75,7 @@ enum EmailRecoveryTimeType { UTCDate? toLatestUTCDate() { switch(this) { case EmailRecoveryTimeType.last7Days: + case EmailRecoveryTimeType.last15Days: case EmailRecoveryTimeType.last30Days: case EmailRecoveryTimeType.last6Months: case EmailRecoveryTimeType.last1Year: diff --git a/lib/features/email_recovery/presentation/model/session_extension.dart b/lib/features/email_recovery/presentation/model/session_extension.dart new file mode 100644 index 000000000..0be0d4b1c --- /dev/null +++ b/lib/features/email_recovery/presentation/model/session_extension.dart @@ -0,0 +1,42 @@ + +import 'package:duration/duration.dart'; +import 'package:email_recovery/email_recovery/capability_deleted_messages_vault.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; +import 'package:model/extensions/session_extension.dart'; + +extension SessionExtension on Session { + + String getRestorationHorizonAsString() { + String restorationHorizon = 'restorationHorizon'; + String defaultHorizon = "15 days"; + + return (getCapabilityProperties(accountId, capabilityDeletedMessagesVault) + ?.props[0] as Map?) + ?[restorationHorizon] + ?? defaultHorizon; + } + + Duration getRestorationHorizonAsDuration() { + try { + String horizonWithCorrectFormat = getRestorationHorizonAsString() + .replaceAll(" days", "d") + .replaceAll(" day", "d") + .replaceAll(" hours", "h") + .replaceAll(" hour", "h") + .replaceAll(" minutes", "m") + .replaceAll(" minute", "m") + .replaceAll(" seconds", "s") + .replaceAll(" second", "s") + .replaceAll(" milliseconds", "ms") + .replaceAll(" millisecond", "ms"); + + return parseDuration(horizonWithCorrectFormat, separator: ' '); + } catch (e) { + return const Duration(days: 15); + } + } + + DateTime getRestorationHorizonAsDateTime() { + return DateTime.now().subtract(getRestorationHorizonAsDuration()); + } +} \ No newline at end of file diff --git a/lib/features/email_recovery/presentation/widgets/date_selection_field/date_selection_field_web_widget.dart b/lib/features/email_recovery/presentation/widgets/date_selection_field/date_selection_field_web_widget.dart index d5e8acd02..17ce46961 100644 --- a/lib/features/email_recovery/presentation/widgets/date_selection_field/date_selection_field_web_widget.dart +++ b/lib/features/email_recovery/presentation/widgets/date_selection_field/date_selection_field_web_widget.dart @@ -18,6 +18,7 @@ class DateSelectionFieldWebWidget extends StatelessWidget { final EmailRecoveryTimeType? recoveryTimeSelected; final OnRecoveryTimeSelected? onRecoveryTimeSelected; final VoidCallback? onTapCalendar; + final DateTime restorationHorizon; const DateSelectionFieldWebWidget({ super.key, @@ -29,6 +30,7 @@ class DateSelectionFieldWebWidget extends StatelessWidget { this.recoveryTimeSelected, this.onRecoveryTimeSelected, this.onTapCalendar, + required this.restorationHorizon }); @override @@ -54,7 +56,7 @@ class DateSelectionFieldWebWidget extends StatelessWidget { endDate: endDate, recoveryTimeSelected: recoveryTimeSelected, onRecoveryTimeSelected: onRecoveryTimeSelected, - items: field.getSupportedTimeTypes(), + items: field.getSupportedTimeTypes(restorationHorizon), ), ), const SizedBox(width: DateSelectionFieldStyles.icCalenderSpace), diff --git a/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_desktop_builder.dart b/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_desktop_builder.dart index bf12da47f..0e7567da3 100644 --- a/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_desktop_builder.dart +++ b/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_desktop_builder.dart @@ -7,6 +7,7 @@ import 'package:tmail_ui_user/features/email_recovery/presentation/model/email_r import 'package:tmail_ui_user/features/email_recovery/presentation/styles/email_recovery_form_styles.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/check_box_has_attachment_widget.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/date_selection_field/date_selection_field_web_widget.dart'; +import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/limits_banner.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/list_button_widget.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/text_input_field/text_input_field_suggestion_widget.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/text_input_field/text_input_field_widget.dart'; @@ -41,6 +42,10 @@ class EmailRecoveryFormDesktopBuilder extends GetWidget child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + LimitsBanner( + bannerContent: AppLocalizations.of(context).recoverDeletedMessagesBannerContent(controller.getRestorationHorizonAsString()), + ), + const SizedBox(height: 16.0), Obx(() => DateSelectionFieldWebWidget( field: EmailRecoveryField.deletionDate, imagePaths: controller.imagePaths, @@ -50,6 +55,7 @@ class EmailRecoveryFormDesktopBuilder extends GetWidget recoveryTimeSelected: controller.deletionDateFieldSelected.value, onTapCalendar: () => controller.onSelectDeletionDateRange(context), onRecoveryTimeSelected: (type) => controller.onDeletionDateTypeSelected(context, type), + restorationHorizon: controller.getRestorationHorizonAsDateTime(), )), Obx(() => DateSelectionFieldWebWidget( field: EmailRecoveryField.receptionDate, @@ -60,6 +66,7 @@ class EmailRecoveryFormDesktopBuilder extends GetWidget recoveryTimeSelected: controller.receptionDateFieldSelected.value, onTapCalendar: () => controller.onSelectReceptionDateRange(context), onRecoveryTimeSelected: (type) => controller.onReceptionDateTypeSelected(context, type), + restorationHorizon: controller.getRestorationHorizonAsDateTime(), )), TextInputFieldWidget( field: EmailRecoveryField.subject, diff --git a/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_mobile_builder.dart b/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_mobile_builder.dart index 8abd5307e..318a312a5 100644 --- a/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_mobile_builder.dart +++ b/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_mobile_builder.dart @@ -7,6 +7,7 @@ import 'package:tmail_ui_user/features/email_recovery/presentation/model/email_r import 'package:tmail_ui_user/features/email_recovery/presentation/styles/email_recovery_form_styles.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/check_box_has_attachment_widget.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/date_selection_field/date_selection_field_mobile_widget.dart'; +import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/limits_banner.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/list_button_widget.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/text_input_field/text_input_field_suggestion_widget.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/text_input_field/text_input_field_widget.dart'; @@ -41,6 +42,10 @@ class EmailRecoveryFormMobileBuilder extends GetWidget child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + LimitsBanner( + bannerContent: AppLocalizations.of(context).recoverDeletedMessagesBannerContent(controller.getRestorationHorizonAsString()), + ), + const SizedBox(height: 16.0), Obx(() => DateSelectionFieldMobileWidget( field: EmailRecoveryField.deletionDate, recoveryTimeSelected: controller.deletionDateFieldSelected.value, diff --git a/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_tablet_builder.dart b/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_tablet_builder.dart index 0ad9f9170..5d300845c 100644 --- a/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_tablet_builder.dart +++ b/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_tablet_builder.dart @@ -7,6 +7,7 @@ import 'package:tmail_ui_user/features/email_recovery/presentation/model/email_r import 'package:tmail_ui_user/features/email_recovery/presentation/styles/email_recovery_form_styles.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/check_box_has_attachment_widget.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/date_selection_field/date_selection_field_web_widget.dart'; +import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/limits_banner.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/list_button_widget.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/text_input_field/text_input_field_suggestion_widget.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/widgets/text_input_field/text_input_field_widget.dart'; @@ -41,6 +42,10 @@ class EmailRecoveryFormTabletBuilder extends GetWidget child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + LimitsBanner( + bannerContent: AppLocalizations.of(context).recoverDeletedMessagesBannerContent(controller.getRestorationHorizonAsString()), + ), + const SizedBox(height: 16.0), Obx(() => DateSelectionFieldWebWidget( field: EmailRecoveryField.deletionDate, imagePaths: controller.imagePaths, @@ -50,6 +55,7 @@ class EmailRecoveryFormTabletBuilder extends GetWidget recoveryTimeSelected: controller.deletionDateFieldSelected.value, onTapCalendar: () => controller.onSelectDeletionDateRange(context), onRecoveryTimeSelected: (type) => controller.onDeletionDateTypeSelected(context, type), + restorationHorizon: controller.getRestorationHorizonAsDateTime(), )), Obx(() => DateSelectionFieldWebWidget( field: EmailRecoveryField.receptionDate, @@ -60,6 +66,7 @@ class EmailRecoveryFormTabletBuilder extends GetWidget recoveryTimeSelected: controller.receptionDateFieldSelected.value, onTapCalendar: () => controller.onSelectReceptionDateRange(context), onRecoveryTimeSelected: (type) => controller.onReceptionDateTypeSelected(context, type), + restorationHorizon: controller.getRestorationHorizonAsDateTime(), )), TextInputFieldWidget( field: EmailRecoveryField.subject, diff --git a/lib/features/email_recovery/presentation/widgets/limits_banner.dart b/lib/features/email_recovery/presentation/widgets/limits_banner.dart new file mode 100644 index 000000000..e540da1ce --- /dev/null +++ b/lib/features/email_recovery/presentation/widgets/limits_banner.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; + +class LimitsBanner extends StatelessWidget { + final String bannerContent; + + const LimitsBanner({ + super.key, + required this.bannerContent, + }); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0), + decoration: BoxDecoration( + color: Colors.yellow[400], + borderRadius: const BorderRadius.all(Radius.circular(8.0)), + ), + child: Center( + child: Text( + bannerContent, + style: const TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.center, + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index ceb581def..e1dcb6c64 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-01-20T18:53:16.325121", + "@@last_modified": "2024-12-03T10:03:02.076482", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -1346,6 +1346,12 @@ "placeholders_order": [], "placeholders": {} }, + "last15Days": "Last 15 days", + "@last15Days": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, "fromMe": "From me", "@fromMe": { "type": "text", @@ -3534,6 +3540,16 @@ "placeholders_order": [], "placeholders": {} }, + "recoverDeletedMessagesBannerContent": "You can recover messages deleted during the past {period}", + "@recoverDeletedMessagesBannerContent": { + "type": "text", + "placeholders_order": [ + "period" + ], + "placeholders": { + "period": {} + } + }, "deletionDate": "Deletion date", "@deletionDate": { "type": "text", diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 33375c6c6..a4504a2c8 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -1374,6 +1374,12 @@ class AppLocalizations { name: 'last7Days'); } + String get last15Days { + return Intl.message( + 'Last 15 days', + name: 'last15Days'); + } + String get fromMe { return Intl.message( 'From me', @@ -3678,6 +3684,14 @@ class AppLocalizations { ); } + String recoverDeletedMessagesBannerContent(String period) { + return Intl.message( + 'You can recover messages deleted during the past $period', + name: 'recoverDeletedMessagesBannerContent', + args: [period] + ); + } + String get deletionDate { return Intl.message( 'Deletion date', diff --git a/pubspec.lock b/pubspec.lock index 58735fd2c..18578f728 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -433,6 +433,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + duration: + dependency: "direct main" + description: + name: duration + sha256: "13e5d20723c9c1dde8fb318cf86716d10ce294734e81e44ae1a817f3ae714501" + url: "https://pub.dev" + source: hosted + version: "4.0.3" email_recovery: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 29a9586eb..29fe75fdc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -251,6 +251,8 @@ dependencies: flutter_web_auth_2: 3.1.1 + duration: 4.0.3 + dev_dependencies: flutter_test: sdk: flutter diff --git a/test/features/email_recovery/session_extension_test.dart b/test/features/email_recovery/session_extension_test.dart new file mode 100644 index 000000000..11df36386 --- /dev/null +++ b/test/features/email_recovery/session_extension_test.dart @@ -0,0 +1,106 @@ + +import 'package:email_recovery/email_recovery/capability_deleted_messages_vault.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/account/account.dart'; +import 'package:jmap_dart_client/jmap/core/capability/default_capability.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; +import 'package:jmap_dart_client/jmap/core/state.dart'; +import 'package:jmap_dart_client/jmap/core/user_name.dart'; +import 'package:tmail_ui_user/features/email_recovery/presentation/model/session_extension.dart'; + +void main() { + + group('session extension test:', () { + test( + 'getRestorationHorizonAsDuration() should return the horizon as a duration when 15 days', + () { + // arrange + final session = Session({}, {AccountId(Id("1")): Account(AccountName("name"), true, false, + {capabilityDeletedMessagesVault: DefaultCapability({"restorationHorizon": "15 days"})})}, + {}, UserName(''), Uri(), Uri(), Uri(), Uri(), State('')); + + // act + final horizon = session.getRestorationHorizonAsDuration(); + + // assert + expect(horizon, const Duration(days: 15)); + }); + + test( + 'getRestorationHorizonAsDuration() should return the horizon as a duration when 1 hour', + () { + // arrange + final session = Session({}, {AccountId(Id("1")): Account(AccountName("name"), true, false, + {capabilityDeletedMessagesVault: DefaultCapability({"restorationHorizon": "1 hour"})})}, + {}, UserName(''), Uri(), Uri(), Uri(), Uri(), State('')); + + // act + final horizon = session.getRestorationHorizonAsDuration(); + + // assert + expect(horizon, const Duration(hours: 1)); + }); + + test( + 'getRestorationHorizonAsDuration() should return the horizon as a duration when 45 minutes', + () { + // arrange + final session = Session({}, {AccountId(Id("1")): Account(AccountName("name"), true, false, + {capabilityDeletedMessagesVault: DefaultCapability({"restorationHorizon": "45 minutes"})})}, + {}, UserName(''), Uri(), Uri(), Uri(), Uri(), State('')); + + // act + final horizon = session.getRestorationHorizonAsDuration(); + + // assert + expect(horizon, const Duration(minutes: 45)); + }); + + test( + 'getRestorationHorizonAsDuration() should return default horizon as a duration when invalid horizon', + () { + // arrange + final session = Session({}, {AccountId(Id("1")): Account(AccountName("name"), true, false, + {capabilityDeletedMessagesVault: DefaultCapability({"restorationHorizon": "invalid"})})}, + {}, UserName(''), Uri(), Uri(), Uri(), Uri(), State('')); + + // act + final horizon = session.getRestorationHorizonAsDuration(); + + // assert + expect(horizon, const Duration(days: 15)); + }); + + test( + 'getRestorationHorizonAsString should return the horizon as a String', + () { + // arrange + final session = Session({}, {AccountId(Id("1")): Account(AccountName("name"), true, false, + {capabilityDeletedMessagesVault: DefaultCapability({"restorationHorizon": "15 days"})})}, + {}, UserName(''), Uri(), Uri(), Uri(), Uri(), State('')); + + // act + final horizon = session.getRestorationHorizonAsString(); + + // assert + expect(horizon, "15 days"); + }); + + test( + 'getRestorationHorizonAsString should return the default horizon as a String when invalid session attribute', + () { + // arrange + final session = Session({}, {AccountId(Id("1")): Account(AccountName("name"), true, false, + {capabilityDeletedMessagesVault: DefaultCapability({"invalid": "15 days"})})}, + {}, UserName(''), Uri(), Uri(), Uri(), Uri(), State('')); + + // act + final horizon = session.getRestorationHorizonAsString(); + + // assert + expect(horizon, "15 days"); + }); + }); +} \ No newline at end of file