fix(sentry): resolve minified exception types on web release

This commit is contained in:
dab246
2026-03-03 11:43:45 +07:00
committed by Dat H. Pham
parent 2e8a11e7eb
commit 437c46f5ff
53 changed files with 133 additions and 109 deletions
+2 -1
View File
@@ -20,10 +20,11 @@ ENV GITHUB_SHA=$GITHUB_SHA \
SENTRY_RELEASE=$SENTRY_RELEASE
RUN ./scripts/prebuild.sh && \
if [ -z "$GITHUB_SHA" ]; then echo "GITHUB_SHA is required for SENTRY_DIST"; exit 1; fi && \
flutter build web --release --source-maps \
--dart-define=SENTRY_RELEASE=$SENTRY_RELEASE \
--dart-define=SENTRY_DIST=$GITHUB_SHA && \
if [ -n "$SENTRY_AUTH_TOKEN" ] && [ -n "$SENTRY_ORG" ] && [ -n "$SENTRY_PROJECT" ] && [ -n "$SENTRY_RELEASE" ]; then \
if [ -n "$SENTRY_AUTH_TOKEN" ] && [ -n "$SENTRY_ORG" ] && [ -n "$SENTRY_PROJECT" ] && [ -n "$SENTRY_RELEASE" ] && [ -n "$GITHUB_SHA" ]; then \
echo "Sentry configuration detected, uploading sourcemaps..." && \
curl -sL https://sentry.io/get-cli/ | SENTRY_CLI_VERSION=2.20.7 bash && \
sentry-cli releases new "$SENTRY_RELEASE" && \
@@ -1,12 +1,8 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
import 'package:equatable/equatable.dart';
class AddressException extends AppBaseException with EquatableMixin {
class AddressException extends AppBaseException {
const AddressException(super.message);
@override
String get exceptionName => 'AddressException';
@override
List<Object?> get props => [message, exceptionName];
}
@@ -1,15 +1,20 @@
abstract class AppBaseException implements Exception {
import 'package:equatable/equatable.dart';
abstract class AppBaseException with EquatableMixin implements Exception {
final String? message;
const AppBaseException([this.message]);
@override
String toString() {
if (message != null && message!.isNotEmpty) {
if (message?.isNotEmpty == true) {
return '$exceptionName: $message';
}
return exceptionName;
}
String get exceptionName;
@override
List<Object?> get props => [message];
}
@@ -1,12 +1,7 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
import 'package:equatable/equatable.dart';
abstract class DownloadFileException extends AppBaseException
with EquatableMixin {
abstract class DownloadFileException extends AppBaseException {
const DownloadFileException(super.message);
@override
List<Object?> get props => [message, exceptionName];
}
class CommonDownloadFileException extends DownloadFileException {
@@ -1,11 +1,7 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
import 'package:equatable/equatable.dart';
abstract class FileException extends AppBaseException with EquatableMixin {
abstract class FileException extends AppBaseException {
const FileException(super.message);
@override
List<Object?> get props => [message, exceptionName];
}
class NotFoundFileInFolderException extends FileException {
@@ -1,14 +1,10 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
import 'package:equatable/equatable.dart';
class PlatformException extends AppBaseException with EquatableMixin {
class PlatformException extends AppBaseException {
const PlatformException(super.message);
@override
String get exceptionName => 'PlatformException';
@override
List<Object?> get props => [message, exceptionName];
}
class NoSupportPlatformException extends PlatformException {
+1 -1
View File
@@ -88,7 +88,7 @@ class MailAddress with EquatableMixin {
if (postChar == '.') {
var lastChar = address[pos - 1];
if (lastChar == '@' || lastChar == '.') {
throw const AddressException('Subdomain expected before "." or duplicate "." in "address"');
throw AddressException('Subdomain expected before "." or duplicate "." in "$address"');
}
domainSB.write('.');
pos++;
+6
View File
@@ -1,6 +1,7 @@
import 'package:core/utils/application_manager.dart';
import 'package:core/utils/build_utils.dart';
import 'package:core/utils/config/env_loader.dart';
import 'package:core/utils/app_logger.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
/// Holds configuration values for initializing Sentry.
@@ -69,6 +70,11 @@ class SentryConfig {
final appVersion = await ApplicationManager().getAppVersion();
const sentryDist = String.fromEnvironment('SENTRY_DIST');
logTrace(
'SentryConfig::load: sentryDist is $sentryDist,'
'appVersion is $appVersion',
webConsoleEnabled: true,
);
return SentryConfig(
dsn: sentryDSN,
+39 -12
View File
@@ -55,27 +55,54 @@ class SentryInitializer {
SentryEvent event,
Hint? hint,
) async {
final req = event.request;
if (req == null) return event;
event.request = _sanitizeRequest(event.request);
event.exceptions = _deminifyExceptions(event.exceptions);
final sanitizedHeaders = Map<String, String>.from(req.headers)
..removeWhere(
(k, _) => _blockedHeaderPatterns.any(
(p) => k.toLowerCase().contains(p),
),
);
return event;
}
final sanitizedRequest = SentryRequest(
static SentryRequest? _sanitizeRequest(SentryRequest? req) {
if (req == null) return null;
return SentryRequest(
url: req.url,
method: req.method,
headers: sanitizedHeaders,
headers: _sanitizeHeaders(req.headers),
queryString: req.queryString,
cookies: null,
data: null,
);
}
event.request = sanitizedRequest;
static Map<String, String> _sanitizeHeaders(Map<String, String> headers) {
return Map<String, String>.from(headers)
..removeWhere(
(key, _) => _blockedHeaderPatterns.any(
(pattern) => key.toLowerCase().contains(pattern),
),
);
}
return event;
static List<SentryException>? _deminifyExceptions(
List<SentryException>? exceptions,
) {
if (exceptions == null) return null;
return exceptions.map((e) {
if (e.type?.startsWith('minified:') == true) {
final rawValue = e.value?.trim() ?? '';
final extractedType = RegExp(r'^([A-Za-z_][A-Za-z0-9_]*)\s*:')
.firstMatch(rawValue)
?.group(1) ??
RegExp(r"Instance of '([^']+)'").firstMatch(rawValue)?.group(1);
if (extractedType != null &&
extractedType.isNotEmpty &&
extractedType != 'minified' &&
!extractedType.startsWith('minified:')) {
e.type = extractedType;
}
}
return e;
}).toList();
}
}
@@ -1,7 +1,7 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
class NotFoundDataWithThisKeyException extends AppBaseException {
NotFoundDataWithThisKeyException([super.message]);
const NotFoundDataWithThisKeyException([super.message]);
@override
String get exceptionName => 'NotFoundDataWithThisKeyException';
@@ -17,7 +17,7 @@ class LocalStorageManager {
if (entry != null) {
return entry.value;
} else {
throw NotFoundDataWithThisKeyException();
throw const NotFoundDataWithThisKeyException();
}
}
@@ -19,7 +19,7 @@ class SessionStorageManager {
if (entry != null) {
return entry.value;
} else {
throw NotFoundDataWithThisKeyException();
throw const NotFoundDataWithThisKeyException();
}
}
@@ -82,7 +82,7 @@ extension HandleLabelForEmailExtension on SingleEmailController {
emitFailure(
controller: this,
failure: AddALabelToAnEmailFailure(
exception: LabelKeywordIsNull(),
exception: const LabelKeywordIsNull(),
labelDisplay: labelDisplay,
),
);
@@ -290,7 +290,7 @@ extension HandleLabelForEmailExtension on SingleEmailController {
emitFailure(
controller: this,
failure: RemoveALabelFromAnEmailFailure(
exception: LabelKeywordIsNull(),
exception: const LabelKeywordIsNull(),
labelDisplay: labelDisplay,
),
);
@@ -110,7 +110,7 @@ class LabelApi
final labelId = label.id;
if (labelId == null) {
throw LabelIdIsNull();
throw const LabelIdIsNull();
}
final method = SetLabelMethod(accountId)..addDestroy({labelId});
@@ -1,14 +1,14 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
class LabelKeywordIsNull extends AppBaseException {
LabelKeywordIsNull([super.message = 'Label keyword is null']);
const LabelKeywordIsNull([super.message = 'Label keyword is null']);
@override
String get exceptionName => 'LabelKeywordIsNull';
}
class LabelIdIsNull extends AppBaseException {
LabelIdIsNull([super.message = 'Label id is null']);
const LabelIdIsNull([super.message = 'Label id is null']);
@override
String get exceptionName => 'LabelIdIsNull';
@@ -93,7 +93,7 @@ extension HandleLabelActionTypeExtension on LabelController {
if (labelId == null) {
consumeState(
Stream.value(Left(EditLabelFailure(LabelIdIsNull()))),
Stream.value(Left(EditLabelFailure(const LabelIdIsNull()))),
);
return;
}
@@ -55,7 +55,7 @@ class DownloadAttachmentHasTokenExpiredException extends AppBaseException {
final String refreshToken;
DownloadAttachmentHasTokenExpiredException(this.refreshToken)
: super('Token expired for refresh token: $refreshToken');
: super('Token expired for refresh token');
@override
String get exceptionName => 'DownloadAttachmentHasTokenExpiredException';
@@ -102,3 +102,10 @@ class SaasServerUriIsNull extends AppBaseException {
@override
String get exceptionName => 'SaasServerUriIsNull';
}
class AutoRedirectToAppAfterStoreAuthorizeDestinationUrlException extends AppBaseException {
AutoRedirectToAppAfterStoreAuthorizeDestinationUrlException([super.message]);
@override
String get exceptionName => 'AutoRedirectToAppAfterStoreAuthorizeDestinationUrlException';
}
@@ -438,7 +438,7 @@ class MailboxAPI with HandleSetErrorMixin, SessionMixin, MailAPIMixin {
if (setMailboxResponse?.updated?.containsKey(request.mailboxId.id) ?? false) {
return true;
} else {
throw SetMailboxRightsException();
throw const SetMailboxRightsException();
}
}
@@ -1,7 +1,7 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
class NullSessionOrAccountIdException extends AppBaseException {
NullSessionOrAccountIdException(
const NullSessionOrAccountIdException(
[super.message = 'session and accountId should not be null']);
@override
@@ -1,7 +1,7 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
class SetMailboxRightsException extends AppBaseException {
SetMailboxRightsException(
const SetMailboxRightsException(
[super.message = 'Failed to update mailbox rights.']);
@override
@@ -1507,7 +1507,7 @@ class MailboxController extends BaseMailboxController
consumeState(_subaddressingInteractor.execute(session, accountId, allowSubaddressingRequest));
} else {
handleSubAddressingFailure(
SubaddressingFailure.withException(NullSessionOrAccountIdException()),
SubaddressingFailure.withException(const NullSessionOrAccountIdException()),
);
}
@@ -1,8 +1,6 @@
import 'package:equatable/equatable.dart';
import 'package:core/domain/exceptions/app_base_exception.dart';
abstract class VerifyNameException extends AppBaseException
with EquatableMixin {
abstract class VerifyNameException extends AppBaseException {
static const emptyName = 'The name cannot be empty!';
static const duplicatedName = 'The name already exists!';
static const nameContainSpecialCharacter =
@@ -37,7 +37,7 @@ class ForwardingAPI with HandleSetErrorMixin {
final tMailForwardResult = result?.list.firstOrNull;
if (tMailForwardResult == null) {
throw NotFoundForwardException();
throw const NotFoundForwardException();
}
return tMailForwardResult;
@@ -86,6 +86,6 @@ class ForwardingAPI with HandleSetErrorMixin {
return (newForward, methodException);
}
throw methodException ?? NotFoundForwardException();
throw methodException ?? const NotFoundForwardException();
}
}
@@ -1,28 +1,28 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
class NotFoundForwardException extends AppBaseException {
NotFoundForwardException([super.message]);
const NotFoundForwardException([super.message]);
@override
String get exceptionName => 'NotFoundForwardException';
}
class UpdateForwardException extends AppBaseException {
UpdateForwardException([super.message]);
const UpdateForwardException([super.message]);
@override
String get exceptionName => 'UpdateForwardException';
}
class RecipientListIsEmptyException extends AppBaseException {
RecipientListIsEmptyException([super.message]);
const RecipientListIsEmptyException([super.message]);
@override
String get exceptionName => 'RecipientListIsEmptyException';
}
class RecipientListWithInvalidEmailsException extends AppBaseException {
RecipientListWithInvalidEmailsException([super.message]);
const RecipientListWithInvalidEmailsException([super.message]);
@override
String get exceptionName => 'RecipientListWithInvalidEmailsException';
@@ -37,7 +37,7 @@ extension VerifyDefaultIdentitySupportedExtension on IdentitiesController {
} else {
consumeState(
Stream.value(
Left(EditDefaultIdentityFailure(NullSessionOrAccountIdException())),
Left(EditDefaultIdentityFailure(const NullSessionOrAccountIdException())),
),
);
}
@@ -301,7 +301,7 @@ class _AutocompleteContactTextFieldWithTagsState extends State<AutocompleteConta
final emailAddress = EmailAddress(null, inputText);
if (!_validateEmailAddressIsValid(emailAddress)) {
widget.onExceptionCallback?.call(RecipientListWithInvalidEmailsException());
widget.onExceptionCallback?.call(const RecipientListWithInvalidEmailsException());
_resetInputText();
return;
}
@@ -350,12 +350,12 @@ class _AutocompleteContactTextFieldWithTagsState extends State<AutocompleteConta
}
if (listEmailAddress.isEmpty) {
widget.onExceptionCallback?.call(RecipientListIsEmptyException());
widget.onExceptionCallback?.call(const RecipientListIsEmptyException());
return;
}
if (!_validateListEmailAddressIsValid(listEmailAddress)) {
widget.onExceptionCallback?.call(RecipientListWithInvalidEmailsException());
widget.onExceptionCallback?.call(const RecipientListWithInvalidEmailsException());
return;
}
@@ -414,7 +414,7 @@ class _AutocompleteContactTextFieldWithTagsState extends State<AutocompleteConta
}) {
log('_AutocompleteContactTextFieldWithTagsState::_addEmailAddressToInputFieldAction:emailAddress = $emailAddress');
if (!_validateEmailAddressIsValid(emailAddress)) {
widget.onExceptionCallback?.call(RecipientListWithInvalidEmailsException());
widget.onExceptionCallback?.call(const RecipientListWithInvalidEmailsException());
if (isClearInput) {
_resetInputText();
}
@@ -238,7 +238,7 @@ class VacationController extends BaseController {
consumeState(_updateVacationInteractor.execute(accountId, vacationResponse));
} else {
consumeState(
Stream.value(Left(UpdateVacationFailure(NullSessionOrAccountIdException()))),
Stream.value(Left(UpdateVacationFailure(const NullSessionOrAccountIdException()))),
);
}
}
@@ -101,7 +101,7 @@ class PublicAssetApi {
if (notCreatedError == null && publicAsset != null) return publicAsset;
if (notCreatedError?.type == ErrorMethodResponse.overQuota) {
throw PublicAssetQuotaExceededException(message: notCreatedError?.description);
throw PublicAssetQuotaExceededException(notCreatedError?.description);
}
throw const CannotCreatePublicAssetException();
@@ -8,7 +8,7 @@ class CannotCreatePublicAssetException extends AppBaseException {
}
class PublicAssetQuotaExceededException extends AppBaseException {
const PublicAssetQuotaExceededException({String? message}) : super(message);
const PublicAssetQuotaExceededException([super.message]);
@override
String get exceptionName => 'PublicAssetQuotaExceededException';
@@ -28,7 +28,7 @@ class QuotasAPI {
if (getQuotaResponse?.list.isNotEmpty == true) {
return getQuotaResponse!.list;
} else {
throw NotFoundQuotasException();
throw const NotFoundQuotasException();
}
}
}
@@ -1,14 +1,14 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
class NotFoundQuotasException extends AppBaseException {
NotFoundQuotasException([super.message]);
const NotFoundQuotasException([super.message]);
@override
String get exceptionName => 'NotFoundQuotasException';
}
class QuotasNotSupportedException extends AppBaseException {
QuotasNotSupportedException([super.message]);
const QuotasNotSupportedException([super.message]);
@override
String get exceptionName => 'QuotasNotSupportedException';
@@ -494,7 +494,7 @@ class SearchMailboxController extends BaseMailboxController with MailboxActionHa
));
} else {
handleSubAddressingFailure(
SubaddressingFailure.withException(NullSessionOrAccountIdException()),
SubaddressingFailure.withException(const NullSessionOrAccountIdException()),
);
}
@@ -39,7 +39,7 @@ class ServerSettingsAPI with HandleSetErrorMixin {
)?.list.firstOrNull;
if (serverSettings == null) {
throw NotFoundServerSettingsException();
throw const NotFoundServerSettingsException();
}
return serverSettings;
@@ -81,10 +81,10 @@ class ServerSettingsAPI with HandleSetErrorMixin {
)?.updated ?? {};
if (updateServerSettingsResult.isEmpty) {
throw CanNotUpdateServerSettingsException();
throw const CanNotUpdateServerSettingsException();
}
} on ErrorMethodResponseException catch (_) {
throw CanNotUpdateServerSettingsException();
throw const CanNotUpdateServerSettingsException();
}
try {
@@ -94,12 +94,12 @@ class ServerSettingsAPI with HandleSetErrorMixin {
)?.list.firstOrNull;
if (updatedServerSettings == null) {
throw CanNotUpdateServerSettingsException();
throw const CanNotUpdateServerSettingsException();
}
return updatedServerSettings;
} on ErrorMethodResponseException catch (_) {
throw CanNotUpdateServerSettingsException();
throw const CanNotUpdateServerSettingsException();
}
}
}
@@ -1,21 +1,21 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
class NotFoundServerSettingsException extends AppBaseException {
NotFoundServerSettingsException([super.message]);
const NotFoundServerSettingsException([super.message]);
@override
String get exceptionName => 'NotFoundServerSettingsException';
}
class NotFoundSettingOptionException extends AppBaseException {
NotFoundSettingOptionException([super.message]);
const NotFoundSettingOptionException([super.message]);
@override
String get exceptionName => 'NotFoundSettingOptionException';
}
class CanNotUpdateServerSettingsException extends AppBaseException {
CanNotUpdateServerSettingsException([super.message]);
const CanNotUpdateServerSettingsException([super.message]);
@override
String get exceptionName => 'CanNotUpdateServerSettingsException';
@@ -17,7 +17,7 @@ class GetServerSettingInteractor {
final serverSetting = await _serverSettingsRepository.getServerSettings(accountId);
final settingOption = serverSetting.settings;
if (settingOption == null) {
yield Left(GetServerSettingFailure(NotFoundSettingOptionException()));
yield Left(GetServerSettingFailure(const NotFoundSettingOptionException()));
} else {
yield Right(GetServerSettingSuccess(settingOption));
}
@@ -27,7 +27,7 @@ class UpdateServerSettingInteractor {
);
final settingOption = serverSetting.settings;
if (settingOption == null) {
yield Left(UpdateServerSettingFailure(NotFoundServerSettingsException()));
yield Left(UpdateServerSettingFailure(const NotFoundServerSettingsException()));
} else {
yield Right(UpdateServerSettingSuccess(settingOption));
}
@@ -32,7 +32,7 @@ class ThreadDetailRepositoryImpl implements ThreadDetailRepository {
.getThreadById(threadId, accountId);
if (originalEmailIds.isEmpty) {
throw EmptyThreadDetailException();
throw const EmptyThreadDetailException();
}
final filteredEmailIds = await Future.wait(
@@ -1,7 +1,7 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
class EmptyThreadDetailException extends AppBaseException {
EmptyThreadDetailException([super.message]);
const EmptyThreadDetailException([super.message]);
@override
String get exceptionName => 'EmptyThreadDetailException';
@@ -112,7 +112,7 @@ extension AddLabelToThreadExtension on ThreadDetailController {
consumeState(
Stream.value(Left(
AddALabelToAThreadFailure(
exception: LabelKeywordIsNull(),
exception: const LabelKeywordIsNull(),
labelDisplay: labelDisplay,
),
)),
@@ -44,7 +44,7 @@ extension RemoveLabelFromThreadExtension on ThreadDetailController {
emitFailure(
controller: this,
failure: RemoveALabelFromAThreadFailure(
exception: LabelKeywordIsNull(),
exception: const LabelKeywordIsNull(),
labelDisplay: labelDisplay,
),
);
@@ -226,7 +226,7 @@ class FileUploader {
charset: fileCharset);
} else {
logWarning('FileUploader::_parsingResponse(): DataResponseIsNullException');
throw DataResponseIsNullException();
throw const DataResponseIsNullException();
}
}
}
@@ -1,7 +1,7 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
class PickFileCanceledException extends AppBaseException {
PickFileCanceledException([super.message]);
const PickFileCanceledException([super.message]);
@override
String get exceptionName => 'PickFileCanceledException';
@@ -1,7 +1,7 @@
import 'package:core/domain/exceptions/app_base_exception.dart';
class DataResponseIsNullException extends AppBaseException {
DataResponseIsNullException([super.message]);
const DataResponseIsNullException([super.message]);
@override
String get exceptionName => 'DataResponseIsNullException';
@@ -29,7 +29,7 @@ class LocalFilePickerInteractor {
.toList();
yield Right<Failure, Success>(LocalFilePickerSuccess(listFileInfo));
} else {
yield Left<Failure, Success>(LocalFilePickerFailure(PickFileCanceledException()));
yield Left<Failure, Success>(LocalFilePickerFailure(const PickFileCanceledException()));
}
} catch (exception) {
yield Left<Failure, Success>(LocalFilePickerFailure(exception));
@@ -26,7 +26,7 @@ class LocalImagePickerInteractor {
final fileInfo = filePickerResult!.files.first.toFileInfo();
yield Right<Failure, Success>(LocalImagePickerSuccess(fileInfo));
} else {
yield Left<Failure, Success>(LocalImagePickerFailure(PickFileCanceledException()));
yield Left<Failure, Success>(LocalImagePickerFailure(const PickFileCanceledException()));
}
} catch (exception) {
yield Left<Failure, Success>(LocalImagePickerFailure(exception));
+4 -8
View File
@@ -1,26 +1,22 @@
import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
import 'package:core/domain/exceptions/app_base_exception.dart';
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
class InvalidCapability extends AppBaseException with EquatableMixin {
class InvalidCapability extends AppBaseException {
const InvalidCapability([super.message]);
@override
String get exceptionName => 'InvalidCapability';
@override
List<Object?> get props => [message];
}
class SessionMissingCapability extends InvalidCapability {
final Set<CapabilityIdentifier> capabilityIdentifiers;
const SessionMissingCapability(this.capabilityIdentifiers)
SessionMissingCapability(this.capabilityIdentifiers)
: super('Missing capabilities $capabilityIdentifiers');
@override
String get exceptionName => 'SessionMissingCapability';
@override
List<Object?> get props => [capabilityIdentifiers, ...super.props];
List<Object?> get props => [capabilityIdentifiers];
}
@@ -7,6 +7,9 @@ abstract class PermissionException with EquatableMixin implements Exception {
String get exceptionName;
@override
List<Object?> get props => [message];
@override
String toString() {
if (message != null) {
+2 -3
View File
@@ -110,17 +110,16 @@ class NoNetworkError extends RemoteException {
}
class RefreshTokenFailedException extends RemoteException {
final int? statusCode;
RefreshTokenFailedException({
super.message =
'Refresh Token failed with 400 Bad Request. The session is invalid/revoked.',
this.statusCode = 400,
super.code = 400,
});
@override
String get exceptionName => 'RefreshTokenFailedException';
@override
String toString() => "$exceptionName(status: $statusCode): $message";
String toString() => "$exceptionName(status: $code): $message";
}
-1
View File
@@ -10,7 +10,6 @@ import 'package:core/presentation/utils/app_toast.dart';
import 'package:core/utils/app_logger.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_appauth_web/authorization_exception.dart';
import 'package:flutter_svg/svg.dart';
import 'package:jmap_dart_client/jmap/core/error/method/error_method_response.dart';
import 'package:jmap_dart_client/jmap/core/error/method/exception/error_method_response_exception.dart';
@@ -45,7 +45,7 @@ void main() {
test('should rethrow exception when ServerSettingsAPI throws exception',() async {
// arrange
when(serverSettingsAPI.getServerSettings(any))
.thenThrow(NotFoundServerSettingsException());
.thenThrow(const NotFoundServerSettingsException());
// assert
expect(
@@ -71,7 +71,7 @@ void main() {
test('should rethrow exception when ServerSettingsAPI throws exception',() async {
// arrange
when(serverSettingsAPI.updateServerSettings(any, any, any))
.thenThrow(CanNotUpdateServerSettingsException());
.thenThrow(const CanNotUpdateServerSettingsException());
// assert
expect(
@@ -38,7 +38,7 @@ void main() {
test('should rethrow exception when ServerSettingsDataSource throws exception', () async {
// arrange
when(serverSettingsDataSource.getServerSettings(accountId))
.thenThrow(NotFoundServerSettingsException());
.thenThrow(const NotFoundServerSettingsException());
// assert
expect(
@@ -64,7 +64,7 @@ void main() {
test('should rethrow exception when ServerSettingsDataSource throws exception', () async {
// arrange
when(serverSettingsDataSource.updateServerSettings(session, accountId, serverSettings))
.thenThrow(NotFoundServerSettingsException());
.thenThrow(const NotFoundServerSettingsException());
// assert
expect(
@@ -39,7 +39,7 @@ void main() {
test('should return left with exception returned from repository', () {
// arrange
final exception = NotFoundServerSettingsException();
const exception = NotFoundServerSettingsException();
when(serverSettingsRepository.getServerSettings(any)).thenThrow(exception);
// assert
@@ -45,7 +45,7 @@ void main() {
test('should return left with exception returned from repository', () {
// arrange
final exception = NotFoundServerSettingsException();
const exception = NotFoundServerSettingsException();
when(serverSettingsRepository.updateServerSettings(any, any, any))
.thenThrow(exception);