Files
oott/frontend/test/helpers/backend_test_harness.dart
T
rzuastiandClaude Opus 4.8 67b94b89a1 Move backend config to a dialog; group settings into cards
Settings screen now splits responsibilities:
- Backend URL + API key move into a Test/Save popup dialog
  (backend_config_dialog.dart), reachable via a "Re-configure" action.
  Per M3 the Test button is left-aligned (neutral) with Cancel/Save
  grouped trailing. On first run the dialog auto-opens non-dismissible.
- The screen shows the connection read-only (URL plain, key masked with
  reveal) in a "Backend connection" card, and groups Theme + Push into an
  "App settings" card. Theme and push apply immediately, no Save button.
- Align all card titles to titleLarge across home/status/settings.

Adds a test seam (dioBuilderForTesting) so reconfigure keeps the mock Dio
in widget tests instead of issuing real requests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 18:15:10 -04:00

71 lines
2.6 KiB
Dart

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;
// Keep the mock client even after a reconfigure (e.g. saving the backend
// settings) so no test ever issues a real network request.
BackendAPI.dioBuilderForTesting = (_, _) => dio;
return adapter;
}