mirror of
https://github.com/kuhyx/testsAndMisc-archive.git
synced 2026-11-11 12:07:34 +01:00
billsplit was a standalone Flutter app in ~/Downloads with one commit and no git remote — that directory was the only copy of its history. Three things the move needed beyond copying the tree: - The root .gitignore silently swallowed 32 of its files (*.png, *.ico, *.manifest). Ignored files do not error on `git add`, they just vanish, so this would have committed an app that cannot build. Added a trailing block of ! overrides plus .binary-allowlist (which did not exist yet) — the documented in-repo exception for binaries a build genuinely needs. The ../testsAndMisc_binaries/ symlink scheme does not apply: those directories are gone, and a symlinked PNG breaks a fresh clone. - billsplit/.github/workflows/ci.yaml was inert once nested; GitHub only reads workflows at the repository root. Relocated with a working-directory and a billsplit/** path filter. - The app's coverage gate moved to python_pkg/billsplit_coverage/ so every Python file stays under python_pkg/, and gained a test suite at 100% branch coverage as that location requires. billsplit/ now holds only Dart. Also replaces the stock Flutter icon with a family icon from the shared generator. The glyph is a filled silhouette because the family's 72px stroke cannot carry a fine torn edge, and the split is an evenodd-cut perforation so the holes stay transparent on the foreground and monochrome layers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
79 lines
2.6 KiB
Dart
79 lines
2.6 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:billsplit/state/app_state.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
const _pickerChannel = MethodChannel('miguelruivo.flutter.plugins.filepicker');
|
|
const _pathChannel = MethodChannel('plugins.flutter.io/path_provider');
|
|
|
|
/// Mocks the file_picker method channel.
|
|
///
|
|
/// `pickResult`: bytes returned by pickFiles (null → user cancelled).
|
|
/// `saveResult`: path returned by saveFile (null → user cancelled).
|
|
/// `saveThrows`: saveFile raises a PlatformException.
|
|
void mockFilePicker({
|
|
Uint8List? pickResult,
|
|
String? pickName,
|
|
String? saveResult,
|
|
bool saveThrows = false,
|
|
}) {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
|
.setMockMethodCallHandler(_pickerChannel, (call) async {
|
|
if (call.method == 'save') {
|
|
if (saveThrows) {
|
|
throw PlatformException(code: 'boom', message: 'disk full');
|
|
}
|
|
return saveResult;
|
|
}
|
|
// pickFiles ('custom'/'any'/...)
|
|
if (pickResult == null) return null;
|
|
return <Map<dynamic, dynamic>>[
|
|
{
|
|
'path': '/tmp/${pickName ?? 'picked.json'}',
|
|
'name': pickName ?? 'picked.json',
|
|
'size': pickResult.length,
|
|
'bytes': pickResult,
|
|
},
|
|
];
|
|
});
|
|
}
|
|
|
|
/// Points path_provider's documents directory at [dir].
|
|
void mockPathProvider(Directory dir) {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
|
.setMockMethodCallHandler(_pathChannel, (call) async => dir.path);
|
|
}
|
|
|
|
/// Clears both channel mocks.
|
|
void clearChannelMocks() {
|
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
|
..setMockMethodCallHandler(_pickerChannel, null)
|
|
..setMockMethodCallHandler(_pathChannel, null);
|
|
}
|
|
|
|
/// Creates an [AppState] persisted under a fresh temp directory.
|
|
AppState tempState() {
|
|
final dir = Directory.systemTemp.createTempSync('billsplit_ui');
|
|
addTearDown(() => dir.deleteSync(recursive: true));
|
|
return AppState(overrideDir: dir)..loaded = true;
|
|
}
|
|
|
|
/// Pumps [home] inside the app shell with [state] provided.
|
|
Future<void> pumpApp(WidgetTester tester, AppState state, Widget home) {
|
|
return tester.pumpWidget(
|
|
ChangeNotifierProvider.value(
|
|
value: state,
|
|
child: MaterialApp(home: home),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Fires the debounced save timer so tests end with no pending timers.
|
|
Future<void> flushSaves(WidgetTester tester) =>
|
|
tester.pump(const Duration(milliseconds: 450));
|