mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 13:47:47 +01:00
main.dart 538 -> 130, policy.dart 272 -> 85, enforcement_status_card.dart 268 -> 145, plus both test files. Every lib split uses part/part of rather than import. The first attempt used import+export and the analyzer gave 30 errors like "The name '_Card' isn't a class": Dart privates are visible to the whole LIBRARY, and a separate file is a separate library unless it is a part. The test splits separated groups from the testWidgets() calls that had been initialising the binding implicitly, so four tests failed with "Binding has not yet been initialized" - both halves now call ensureInitialized() explicitly. 94 tests passing before and after; flutter analyze reports no issues. focus_owner/analysis_options.yaml has an uncommitted change from an earlier session and is deliberately left unstaged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
89 lines
3.4 KiB
Dart
89 lines
3.4 KiB
Dart
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:focus_owner/device_policy.dart';
|
|
|
|
/// Builds a channel whose handler answers from [responses], recording calls.
|
|
({MethodChannel channel, List<MethodCall> calls}) _fakeChannel(
|
|
Map<String, Object?> responses,
|
|
) {
|
|
const channel = MethodChannel('test/device_policy');
|
|
final calls = <MethodCall>[];
|
|
// hasHomeLocation is read on every status refresh, so it is defaulted here
|
|
// rather than restated in each widget test. An explicit stub still wins,
|
|
// which is what the geofence-state tests rely on.
|
|
final stubs = {'hasHomeLocation': false, ...responses};
|
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
|
.setMockMethodCallHandler(channel, (call) async {
|
|
calls.add(call);
|
|
if (!stubs.containsKey(call.method)) {
|
|
throw PlatformException(code: 'unimplemented', message: 'no stub');
|
|
}
|
|
return stubs[call.method];
|
|
});
|
|
return (channel: channel, calls: calls);
|
|
}
|
|
|
|
Map<String, Object?> _statusMap({bool isDeviceOwner = false}) => {
|
|
'packageName': 'com.kuhy.focus_owner',
|
|
'isDeviceOwner': isDeviceOwner,
|
|
'isAdminActive': isDeviceOwner,
|
|
'sdkInt': 36,
|
|
'restrictionsApplied': false,
|
|
};
|
|
|
|
|
|
|
|
void main() {
|
|
// Explicit since the split moved the testWidgets() group that used to
|
|
// initialise the binding implicitly.
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
group('DevicePolicyStatus', () {
|
|
test('parses the native status map', () {
|
|
final status = DevicePolicyStatus.fromMap(_statusMap(isDeviceOwner: true));
|
|
expect(status.packageName, 'com.kuhy.focus_owner');
|
|
expect(status.isDeviceOwner, isTrue);
|
|
expect(status.sdkInt, 36);
|
|
});
|
|
|
|
test('this build never reports restrictions as applied', () {
|
|
// Not a claim that nothing is enforced -- the app is live and hiding
|
|
// packages, and it does apply user restrictions once the VPN and DNS
|
|
// layers are locked. The native side simply never reads this back, so
|
|
// it is always false; the real state is the hidden-app count.
|
|
expect(
|
|
DevicePolicyStatus.fromMap(_statusMap()).restrictionsApplied,
|
|
isFalse,
|
|
);
|
|
});
|
|
});
|
|
|
|
group('DevicePolicy', () {
|
|
test('status() invokes the native status method', () async {
|
|
final fake = _fakeChannel({'status': _statusMap()});
|
|
final status = await DevicePolicy(fake.channel).status();
|
|
expect(fake.calls.single.method, 'status');
|
|
expect(status.isDeviceOwner, isFalse);
|
|
});
|
|
|
|
test('releaseDeviceOwner() forwards the native result', () async {
|
|
final fake = _fakeChannel({'releaseDeviceOwner': true});
|
|
expect(await DevicePolicy(fake.channel).releaseDeviceOwner(), isTrue);
|
|
expect(fake.calls.single.method, 'releaseDeviceOwner');
|
|
});
|
|
|
|
test('releaseDeviceOwner() reports failure rather than throwing', () async {
|
|
// The button that calls this is the last resort before a factory reset,
|
|
// so a failure must surface in the UI, never as an unhandled error.
|
|
final fake = _fakeChannel({'releaseDeviceOwner': false});
|
|
expect(await DevicePolicy(fake.channel).releaseDeviceOwner(), isFalse);
|
|
});
|
|
|
|
test('releaseDeviceOwner() treats a null reply as failure', () async {
|
|
final fake = _fakeChannel({'releaseDeviceOwner': null});
|
|
expect(await DevicePolicy(fake.channel).releaseDeviceOwner(), isFalse);
|
|
});
|
|
});
|
|
}
|