Files
Qlyra/test/android_permission_matrix_test.dart
sevenhill 50816588e4
Build Android (FCM) / build-android-fcm (push) Canceled after 0s
Build Android / build-android (push) Canceled after 0s
Build iOS / build-ios (push) Canceled after 0s
Build Linux / build-linux (push) Canceled after 0s
Build macOS / build-macos (push) Canceled after 0s
Build Windows / build-windows (push) Canceled after 0s
Release (main) / android (oneme) (push) Canceled after 0s
Release (main) / android (qlyra) (push) Canceled after 0s
Release (main) / windows (push) Canceled after 0s
Release (main) / linux (push) Canceled after 0s
Release (main) / macos (push) Canceled after 0s
Release (main) / ios (push) Canceled after 0s
Release (main) / release (push) Canceled after 0s
Update Qlyra application
2026-08-30 22:53:15 +03:00

74 lines
2.7 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
void main() {
final manifest = File('android/app/src/main/AndroidManifest.xml');
final matrix = File('tool/android_permissions.json');
test('every Android manifest permission is present in the policy matrix', () {
final declared = RegExp(r'<uses-permission\s+android:name="([^"]+)"')
.allMatches(manifest.readAsStringSync())
.map((match) => match.group(1)!)
.toSet();
final entries = (jsonDecode(matrix.readAsStringSync()) as List)
.cast<Map<String, dynamic>>();
final documented = entries
.map((entry) => entry['permission'] as String)
.toSet();
expect(entries.length, documented.length);
expect(documented, declared);
for (final entry in entries) {
expect((entry['owner'] as String).trim(), isNotEmpty);
expect((entry['feature'] as String).trim(), isNotEmpty);
expect((entry['trigger'] as String).trim(), isNotEmpty);
}
});
test('runtime-sensitive permissions require a user action', () {
final entries = (jsonDecode(matrix.readAsStringSync()) as List)
.cast<Map<String, dynamic>>();
final byPermission = {
for (final entry in entries) entry['permission'] as String: entry,
};
final sensitive = {
'android.permission.REQUEST_INSTALL_PACKAGES',
'android.permission.CAMERA',
'android.permission.ACCESS_FINE_LOCATION',
'android.permission.ACCESS_COARSE_LOCATION',
'android.permission.RECORD_AUDIO',
'android.permission.BLUETOOTH_CONNECT',
'android.permission.BLUETOOTH_ADVERTISE',
'android.permission.BLUETOOTH_SCAN',
'android.permission.POST_NOTIFICATIONS',
'android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS',
'android.permission.USE_FULL_SCREEN_INTENT',
'android.permission.READ_EXTERNAL_STORAGE',
'android.permission.READ_MEDIA_IMAGES',
'android.permission.READ_MEDIA_VIDEO',
'android.permission.READ_MEDIA_VISUAL_USER_SELECTED',
'android.permission.READ_CONTACTS',
};
for (final permission in sensitive) {
expect(byPermission[permission]?['trigger'], 'user_action');
}
});
test('startup paths do not request notification or full-screen access', () {
final pushSource = File(
'lib/core/push/push_service.dart',
).readAsStringSync();
final mainSource = File('lib/main.dart').readAsStringSync();
final initBody = RegExp(
r'Future<void> init\([\s\S]*?Future<bool> requestPermissionFromUser',
).firstMatch(pushSource)?.group(0);
expect(initBody, isNotNull);
expect(initBody, isNot(contains('requestPermission()')));
expect(mainSource, isNot(contains('_ensureFullScreenIntentPermission')));
});
}