Location search starts a new mission; shrink and center header bar
Ortssuche verschob bisher nur die Karte - der HTML-Demonstrator beginnt bei einer Suche immer eine neue, nach dem gefundenen Ort benannte Mission (setMissionFromPlace(), aufgerufen aus doSearch()). Vorherige Aenderungen gehen dabei nicht verloren, da flushPendingAutosave() (hier: CurrentMissionMetaNotifier._flushNow()) zuerst noch ausstehende Autosaves schreibt. Die Nominatim-Suche wurde dafuer aus MapSearchControls in einen eigenstaendigen NominatimService extrahiert (analog WindService): injectable http.Client, damit sich die Suche in Tests ohne echten Netzwerkzugriff ueberschreiben laesst. CurrentMissionMetaNotifier bekam dafuer startNewFromPlace() (startNew() intern darauf umgebaut, um Duplikation zu vermeiden). Kopfleiste von 86%/64% (Plan-/Fly-Modus) auf einheitlich 70% Bildschirmbreite verkleinert - zentriert war sie durch Align(topCenter) + FractionallySizedBox bereits strukturell korrekt, wirkte bei der vollen Breite aber unausgewogen. Verifiziert: flutter analyze (0 issues), flutter test (64/64, davon 4 neue NominatimService-Tests und 1 neuer Widget-Test fuer den Missions-Reset bei Ortssuche), manuell auf Pixel_10a-Emulator - Suche nach "Rotterdam" setzt Fusszeile auf "Mission: Rotterdam" mit 0 Wegpunkten trotz zuvor bestehender Mission mit Wegpunkten. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
aaec7f0f72
commit
926d805156
@@ -1,16 +1,23 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/testing.dart';
|
||||
|
||||
import 'package:dmc_app/app_mode/app_mode_cubit.dart';
|
||||
import 'package:dmc_app/domain/waypoint/flat_waypoint_list.dart';
|
||||
import 'package:dmc_app/services/database/app_database.dart' hide DroneProfile, Mission;
|
||||
import 'package:dmc_app/services/geocoding/nominatim_service.dart';
|
||||
import 'package:dmc_app/ui/app_shell.dart';
|
||||
import 'package:dmc_app/ui/providers/current_mission_provider.dart';
|
||||
import 'package:dmc_app/ui/providers/database_provider.dart';
|
||||
import 'package:dmc_app/ui/providers/geocoding_provider.dart';
|
||||
import 'package:dmc_app/ui/providers/mission_meta_provider.dart';
|
||||
import 'package:dmc_app/ui/widgets/full_value_chart.dart';
|
||||
import 'package:dmc_app/ui/widgets/halo_menu.dart';
|
||||
import 'package:dmc_app/ui/widgets/header_wind_pill.dart';
|
||||
@@ -442,6 +449,61 @@ void main() {
|
||||
expect(find.text('Location not found'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'Ortssuche legt eine neue, nach dem Ort benannte Mission an',
|
||||
(tester) async {
|
||||
final client = MockClient((request) async => http.Response(
|
||||
jsonEncode([
|
||||
{
|
||||
'lat': '51.9225',
|
||||
'lon': '4.47917',
|
||||
'display_name': 'Rotterdam, South Holland, Netherlands',
|
||||
'address': {'city': 'Rotterdam'},
|
||||
},
|
||||
]),
|
||||
200,
|
||||
));
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
appDatabaseProvider.overrideWithValue(_testDatabase()),
|
||||
nominatimServiceProvider
|
||||
.overrideWithValue(NominatimService(client: client)),
|
||||
],
|
||||
);
|
||||
addTearDown(container.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
UncontrolledProviderScope(
|
||||
container: container,
|
||||
child: BlocProvider(
|
||||
create: (_) => AppModeCubit(),
|
||||
child: const MaterialApp(home: AppShell()),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pump();
|
||||
|
||||
// Bestehenden Wegpunkt anlegen, damit sich pruefen laesst, dass die
|
||||
// Suche die Mission wirklich neu beginnt statt nur die Karte zu
|
||||
// verschieben (HTML-Demonstrator: setMissionFromPlace()).
|
||||
await tester.tap(find.byType(ReticleButton));
|
||||
await tester.pump();
|
||||
expect(container.read(currentMissionProvider), hasLength(1));
|
||||
|
||||
await tester.enterText(find.byType(TextField), 'Rotterdam');
|
||||
await tester.testTextInput.receiveAction(TextInputAction.search);
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
|
||||
expect(container.read(currentMissionMetaProvider).name, 'Rotterdam');
|
||||
expect(container.read(currentMissionMetaProvider).placeName, 'Rotterdam');
|
||||
expect(container.read(currentMissionProvider), isEmpty);
|
||||
|
||||
// Autosave debounced ueber 800ms - abwarten, damit nach Testende kein
|
||||
// Timer mehr aussteht (Doku 7.5).
|
||||
await tester.pump(const Duration(milliseconds: 900));
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'Kameraposition bleibt beim Wechsel Plan -> Fly -> Plan erhalten',
|
||||
(tester) async {
|
||||
|
||||
Reference in New Issue
Block a user