testsAndMisc/focus_owner/test/policy_test.dart
Krzysztof kuhy Rudnicki d9982e53dd Split the focus_owner Dart files under the cap
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
2026-08-16 20:39:13 +02:00

102 lines
3.3 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:focus_owner/policy.dart';
Map<String, Object?> _doc({
Object? schemaVersion = kSupportedSchemaVersion,
Object? curfew = const {'start': '23:00', 'end': '05:00'},
double? latitude,
double? longitude,
}) =>
{
'schema_version': schemaVersion,
'home': {
'latitude': latitude,
'longitude': longitude,
'radius_m': 150.0,
'hysteresis_m': 30.0,
},
'curfew': curfew,
'launcher_package': 'com.qqlabs.minimalistlauncher',
'allowed_packages': ['com.good', 'pl.mbank'],
'night_allowed_packages': ['pl.mbank'],
'never_disable_prefixes': ['com.android.providers'],
'workout_unblock_domains': ['youtube.com'],
'browser_packages': <String>[],
};
void main() {
group('FocusPolicy.fromJson', () {
test('parses a rendered policy', () {
final policy = FocusPolicy.fromJson(_doc());
expect(policy.allowedPackages, {'com.good', 'pl.mbank'});
expect(policy.nightAllowedPackages, {'pl.mbank'});
expect(policy.launcherPackage, 'com.qqlabs.minimalistlauncher');
expect(policy.home.radiusM, 150.0);
});
test('rejects an unknown schema version', () {
// Accepting a newer schema would mean enforcing a misread policy.
expect(
() => FocusPolicy.fromJson(_doc(schemaVersion: 999)),
throwsA(isA<PolicyFormatException>()),
);
});
test('rejects a document with no home object', () {
final doc = _doc()..remove('home');
expect(
() => FocusPolicy.fromJson(doc),
throwsA(isA<PolicyFormatException>()),
);
});
test('rejects a malformed curfew time', () {
expect(
() => FocusPolicy.fromJson(_doc(curfew: {'start': '25:00', 'end': 'x'})),
throwsA(isA<PolicyFormatException>()),
);
});
test('accepts an absent curfew', () {
expect(FocusPolicy.fromJson(_doc(curfew: null)).curfew, isNull);
});
});
group('HomeLocation', () {
test('redacted coordinates are reported as absent', () {
// The committed asset is redacted; enforcement must not treat a missing
// coordinate as (0, 0), which would put "home" in the Atlantic.
final policy = FocusPolicy.fromJson(_doc());
expect(policy.home.hasCoordinates, isFalse);
expect(policy.home.radiusM, 150.0);
});
test('real coordinates are reported as present', () {
final policy =
FocusPolicy.fromJson(_doc(latitude: 52.2297, longitude: 21.0122));
expect(policy.home.hasCoordinates, isTrue);
});
});
group('CurfewWindow', () {
const window = CurfewWindow(startMinutes: 23 * 60, endMinutes: 5 * 60);
test('wraps midnight', () {
expect(window.contains(22 * 60 + 59), isFalse);
expect(window.contains(23 * 60), isTrue);
expect(window.contains(0), isTrue);
expect(window.contains(4 * 60 + 59), isTrue);
expect(window.contains(5 * 60), isFalse);
expect(window.contains(12 * 60), isFalse);
});
test('handles a same-day window', () {
const day = CurfewWindow(startMinutes: 9 * 60, endMinutes: 17 * 60);
expect(day.contains(8 * 60), isFalse);
expect(day.contains(9 * 60), isTrue);
expect(day.contains(17 * 60), isFalse);
});
});
}