implemented dual Nextcloud push registration with separate general and talk apptypes to ensure reliable Talk notification delivery; introduced stacked MessagingStyle notifications for chat threads with support for circular conversation avatars and disk caching
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:marianum_mobile/push/push_status.dart';
|
||||
|
||||
const _liveProxy = 'https://connect.marianum-fulda.de/push-proxy/';
|
||||
const _betaProxy = 'https://connect-beta.marianum-fulda.de/push-proxy/';
|
||||
|
||||
PushTypeStatus _typeStatus({
|
||||
bool nextcloudRegistered = true,
|
||||
String? registeredNcBaseUrl = 'https://cloud.marianum-fulda.de',
|
||||
String? registeredProxyServer = _liveProxy,
|
||||
DateTime? lastRegistrationAt,
|
||||
String? lastRegistrationError,
|
||||
}) => PushTypeStatus(
|
||||
nextcloudRegistered: nextcloudRegistered,
|
||||
registeredNcBaseUrl: registeredNcBaseUrl,
|
||||
registeredProxyServer: registeredProxyServer,
|
||||
lastRegistrationAt: lastRegistrationAt,
|
||||
lastRegistrationError: lastRegistrationError,
|
||||
);
|
||||
|
||||
PushStatusReport _report({
|
||||
bool settingEnabled = true,
|
||||
PushCheck osPermission = PushCheck.ok,
|
||||
PushCheck serverCapability = PushCheck.ok,
|
||||
bool appPasswordPresent = true,
|
||||
bool talkAppPasswordPresent = true,
|
||||
bool keypairPresent = true,
|
||||
PushTypeStatus? general,
|
||||
PushTypeStatus? talk,
|
||||
String? currentProxyServer = _liveProxy,
|
||||
}) => PushStatusReport(
|
||||
settingEnabled: settingEnabled,
|
||||
osPermission: osPermission,
|
||||
serverCapability: serverCapability,
|
||||
appPasswordPresent: appPasswordPresent,
|
||||
talkAppPasswordPresent: talkAppPasswordPresent,
|
||||
keypairPresent: keypairPresent,
|
||||
general: general ?? _typeStatus(),
|
||||
talk: talk ?? _typeStatus(),
|
||||
currentProxyServer: currentProxyServer,
|
||||
);
|
||||
|
||||
PushStatusRow _row(List<PushStatusRow> rows, String label) =>
|
||||
rows.singleWhere((r) => r.label == label);
|
||||
|
||||
void main() {
|
||||
group('buildPushStatusRows', () {
|
||||
test('healthy chain shows nine ok rows in chain order', () {
|
||||
final rows = buildPushStatusRows(_report());
|
||||
expect(rows, hasLength(9));
|
||||
expect(rows.map((r) => r.label), [
|
||||
'Push-Benachrichtigungen aktiviert',
|
||||
'Benachrichtigungsberechtigung',
|
||||
'Server-Unterstützung',
|
||||
'App-Passwörter',
|
||||
'Geräteschlüssel',
|
||||
'Nextcloud-Registrierung (Allgemein)',
|
||||
'Nextcloud-Registrierung (Talk)',
|
||||
'Connect-Registrierung (Allgemein)',
|
||||
'Connect-Registrierung (Talk)',
|
||||
]);
|
||||
expect(rows.every((r) => r.state == PushCheck.ok), isTrue);
|
||||
});
|
||||
|
||||
test('disabled setting fails the first row with a hint', () {
|
||||
final rows = buildPushStatusRows(_report(settingEnabled: false));
|
||||
final row = _row(rows, 'Push-Benachrichtigungen aktiviert');
|
||||
expect(row.state, PushCheck.fail);
|
||||
expect(row.detail, contains('deaktiviert'));
|
||||
});
|
||||
|
||||
test('unloaded capabilities show as unknown, not as failure', () {
|
||||
final rows = buildPushStatusRows(
|
||||
_report(serverCapability: PushCheck.unknown),
|
||||
);
|
||||
final row = _row(rows, 'Server-Unterstützung');
|
||||
expect(row.state, PushCheck.unknown);
|
||||
expect(row.detail, contains('noch nicht geladen'));
|
||||
});
|
||||
|
||||
test('missing talk app password fails the password row and names it', () {
|
||||
final rows = buildPushStatusRows(_report(talkAppPasswordPresent: false));
|
||||
final row = _row(rows, 'App-Passwörter');
|
||||
expect(row.state, PushCheck.fail);
|
||||
expect(row.detail, contains('Talk-App-Passwort fehlt'));
|
||||
});
|
||||
|
||||
test('registered rows carry their URL as detail', () {
|
||||
final rows = buildPushStatusRows(_report());
|
||||
expect(
|
||||
_row(rows, 'Nextcloud-Registrierung (Allgemein)').detail,
|
||||
'https://cloud.marianum-fulda.de',
|
||||
);
|
||||
expect(_row(rows, 'Connect-Registrierung (Talk)').detail, _liveProxy);
|
||||
});
|
||||
|
||||
test('a broken talk registration fails only the talk rows', () {
|
||||
final rows = buildPushStatusRows(
|
||||
_report(
|
||||
talk: _typeStatus(
|
||||
nextcloudRegistered: false,
|
||||
registeredProxyServer: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(
|
||||
_row(rows, 'Nextcloud-Registrierung (Allgemein)').state,
|
||||
PushCheck.ok,
|
||||
);
|
||||
expect(
|
||||
_row(rows, 'Connect-Registrierung (Allgemein)').state,
|
||||
PushCheck.ok,
|
||||
);
|
||||
expect(
|
||||
_row(rows, 'Nextcloud-Registrierung (Talk)').state,
|
||||
PushCheck.fail,
|
||||
);
|
||||
final talkConnect = _row(rows, 'Connect-Registrierung (Talk)');
|
||||
expect(talkConnect.state, PushCheck.fail);
|
||||
expect(talkConnect.detail, contains('ausstehend'));
|
||||
});
|
||||
|
||||
test('proxy endpoint mismatch fails the affected row naming both URLs', () {
|
||||
final report = _report(
|
||||
talk: _typeStatus(registeredProxyServer: _liveProxy),
|
||||
currentProxyServer: _betaProxy,
|
||||
general: _typeStatus(registeredProxyServer: _betaProxy),
|
||||
);
|
||||
expect(report.proxyEndpointMismatch(report.talk), isTrue);
|
||||
expect(report.proxyEndpointMismatch(report.general), isFalse);
|
||||
final row = _row(
|
||||
buildPushStatusRows(report),
|
||||
'Connect-Registrierung (Talk)',
|
||||
);
|
||||
expect(row.state, PushCheck.fail);
|
||||
expect(row.detail, contains('connect.marianum-fulda.de'));
|
||||
expect(row.detail, contains('connect-beta.marianum-fulda.de'));
|
||||
});
|
||||
|
||||
test('per-type registration errors fail only their own connect row', () {
|
||||
final rows = buildPushStatusRows(
|
||||
_report(talk: _typeStatus(lastRegistrationError: 'HTTP 404')),
|
||||
);
|
||||
expect(
|
||||
_row(rows, 'Connect-Registrierung (Allgemein)').state,
|
||||
PushCheck.ok,
|
||||
);
|
||||
final talkRow = _row(rows, 'Connect-Registrierung (Talk)');
|
||||
expect(talkRow.state, PushCheck.fail);
|
||||
expect(talkRow.detail, contains('fehlgeschlagen'));
|
||||
});
|
||||
});
|
||||
|
||||
group('PushStatusReport.readyForTestNotification', () {
|
||||
test('test push only depends on the general chain', () {
|
||||
// Test pushes are Connect direct pushes via the general registration —
|
||||
// a broken talk registration must not disable the test action.
|
||||
final report = _report(
|
||||
talk: _typeStatus(
|
||||
nextcloudRegistered: false,
|
||||
registeredProxyServer: null,
|
||||
lastRegistrationError: 'HTTP 404',
|
||||
),
|
||||
);
|
||||
expect(report.readyForTestNotification, isTrue);
|
||||
});
|
||||
|
||||
test('denied OS permission wins over a complete registration', () {
|
||||
expect(
|
||||
_report(osPermission: PushCheck.fail).readyForTestNotification,
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
test('undetermined OS permission stays permissive', () {
|
||||
expect(
|
||||
_report(osPermission: PushCheck.unknown).readyForTestNotification,
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
|
||||
test('missing general registration is not ready', () {
|
||||
expect(
|
||||
_report(
|
||||
general: _typeStatus(nextcloudRegistered: false),
|
||||
).readyForTestNotification,
|
||||
isFalse,
|
||||
);
|
||||
expect(
|
||||
_report(
|
||||
general: _typeStatus(registeredProxyServer: null),
|
||||
).readyForTestNotification,
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
test('general endpoint mismatch or failed attempt is not ready', () {
|
||||
expect(
|
||||
_report(
|
||||
general: _typeStatus(registeredProxyServer: _liveProxy),
|
||||
talk: _typeStatus(registeredProxyServer: _betaProxy),
|
||||
currentProxyServer: _betaProxy,
|
||||
).readyForTestNotification,
|
||||
isFalse,
|
||||
);
|
||||
expect(
|
||||
_report(
|
||||
general: _typeStatus(lastRegistrationError: 'HTTP 404'),
|
||||
).readyForTestNotification,
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user