mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Add automated test suite for the Flutter frontend
Introduce a headless `flutter test` suite (83 tests) covering models, utilities, every API endpoint, and the five screens, with shared helpers and fixtures so new tests stay terse. API endpoint methods are statically-dispatched extensions on the BackendAPI singleton, so they cannot be mocked via `implements`. Mock at the Dio HTTP-adapter layer (http_mock_adapter) instead, enabled by two small @visibleForTesting seams: BackendAPI.dioForTesting swaps the singleton's Dio, and BackendReachability.forceOnlineForTesting() forces a deterministic online state so polling widgets load. Add frontend/run_tests.sh and document it in CLAUDE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
e6813a78fb
commit
98b5fa267f
@@ -0,0 +1,67 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:frontend/utils/backend_reachability.dart';
|
||||
import 'package:frontend/utils/oott_api.dart';
|
||||
import 'package:frontend/utils/pref_utils.dart';
|
||||
import 'package:http_mock_adapter/http_mock_adapter.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
const _connectivityMethodChannel = MethodChannel(
|
||||
'dev.fluttercommunity.plus/connectivity',
|
||||
);
|
||||
const _connectivityEventChannel = EventChannel(
|
||||
'dev.fluttercommunity.plus/connectivity_status',
|
||||
);
|
||||
|
||||
bool _channelsStubbed = false;
|
||||
|
||||
/// Neutralises the connectivity_plus platform channels so the
|
||||
/// [BackendReachability] singleton can be constructed in tests without the
|
||||
/// plugin throwing `MissingPluginException`. `check` reports a network, and
|
||||
/// the change stream stays open but emits nothing.
|
||||
void _stubConnectivityChannels() {
|
||||
if (_channelsStubbed) return;
|
||||
final messenger =
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger;
|
||||
messenger.setMockMethodCallHandler(_connectivityMethodChannel, (call) async {
|
||||
if (call.method == 'check') return <String>['wifi'];
|
||||
return null;
|
||||
});
|
||||
messenger.setMockStreamHandler(
|
||||
_connectivityEventChannel,
|
||||
MockStreamHandler.inline(onListen: (arguments, events) {}),
|
||||
);
|
||||
_channelsStubbed = true;
|
||||
}
|
||||
|
||||
/// Prepares the backend singletons for a test and returns a [DioAdapter] so the
|
||||
/// test can stub HTTP routes. Call from `setUp`.
|
||||
///
|
||||
/// This (1) seeds mock SharedPreferences, (2) stubs the connectivity channels,
|
||||
/// (3) forces [BackendReachability] online so polling widgets load, and
|
||||
/// (4) swaps the [BackendAPI] singleton's Dio for one backed by a mock adapter.
|
||||
///
|
||||
/// `prefs` are only honoured on the first call within a test isolate, because
|
||||
/// `PrefUtil` caches the SharedPreferences instance after its one-shot init.
|
||||
/// Use [PrefUtil.setValue] for per-test changes after that.
|
||||
Future<DioAdapter> setUpBackendForTest({
|
||||
Map<String, Object> prefs = const {},
|
||||
}) async {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
_stubConnectivityChannels();
|
||||
|
||||
SharedPreferences.setMockInitialValues({
|
||||
'base_url': 'http://test.local/api',
|
||||
'api_key': '',
|
||||
...prefs,
|
||||
});
|
||||
await PrefUtil.init();
|
||||
|
||||
BackendReachability.instance.forceOnlineForTesting();
|
||||
|
||||
final dio = Dio(BaseOptions(baseUrl: 'http://test.local/api'));
|
||||
final adapter = DioAdapter(dio: dio);
|
||||
BackendAPI.instance.dioForTesting = dio;
|
||||
return adapter;
|
||||
}
|
||||
Reference in New Issue
Block a user