fixed client-reported crashes in the pdf viewer, image picker and prosemirror images, mapped webdav errors to user messages and hardened keychain, cache and push stores against io failures

This commit is contained in:
MineTec committed 2026-10-12 17:00:14 +02:00
1 parent c5592f117b
commit 23e4510bf8
19 files changed
+545 -55

No files matched your search

+93
View File
@@ -14,6 +14,9 @@ import 'package:marianum_mobile/api/errors/parse_exception.dart';
import 'package:marianum_mobile/api/errors/permission_exception.dart';
import 'package:nextcloud/nextcloud.dart';
(String, bool) errorUserMessageAndRetry(Object error) =>
(errorToUserMessage(error), errorAllowsRetry(error));
void main() {
group('errorToUserMessage', () {
test('null falls back to the default message', () {
@@ -165,6 +168,96 @@ void main() {
expect(errorToUserMessage(ex), contains('Zu viele Anfragen'));
expect(errorAllowsRetry(ex), isTrue);
});
String davBody(String exception, String message) =>
'<?xml version="1.0" encoding="utf-8"?>\n'
'<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">\n'
' <s:exception>Sabre\\DAV\\Exception\\$exception</s:exception>\n'
' <s:message>$message</s:message>\n'
'</d:error>';
test('parseDavError extracts class and message', () {
final dav = parseDavError(
davBody(
'MethodNotAllowed',
'The resource you tried to create already exists',
),
);
expect(dav?.exception, 'MethodNotAllowed');
expect(dav?.message, 'The resource you tried to create already exists');
expect(parseDavError('<html>nope</html>'), isNull);
});
test('MKCOL 405 on an existing folder says so and allows no retry', () {
final ex = DynamiteApiException(
405,
const {},
davBody(
'MethodNotAllowed',
'The resource you tried to create already exists',
),
);
expect(errorToUserMessage(ex), contains('existiert bereits'));
expect(
errorToTechnicalDetails(ex),
'HTTP 405 MethodNotAllowed: The resource you tried to create already exists',
);
expect(errorAllowsRetry(ex), isFalse);
});
test('other DAV exceptions map to their own messages', () {
expect(
errorToUserMessage(
DynamiteApiException(
412,
const {},
davBody('PreconditionFailed', 'x'),
),
),
contains('Zielort'),
);
expect(
errorToUserMessage(
DynamiteApiException(409, const {}, davBody('Conflict', 'x')),
),
contains('übergeordnete Ordner'),
);
expect(
errorUserMessageAndRetry(
DynamiteApiException(423, const {}, davBody('Locked', 'x')),
),
(
'Der Eintrag wird gerade bearbeitet. Bitte versuche es gleich erneut.',
true,
),
);
expect(
errorToUserMessage(
DynamiteApiException(
507,
const {},
davBody('InsufficientStorage', 'x'),
),
),
contains('Speicherplatz'),
);
});
test(
'unknown DAV exceptions keep the status mapping but name the class',
() {
final ex = DynamiteApiException(
404,
const {},
davBody('NotFound', 'File not found'),
);
expect(errorToUserMessage(ex), const NotFoundException().userMessage);
expect(
errorToTechnicalDetails(ex),
'HTTP 404 NotFound: File not found',
);
},
);
});
group('errorToTechnicalDetails', () {