mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-14 09:50:30 +00:00
feat: Enhance device configuration and location tracking features
- Refetch device info after updating settings in device_config_screen.dart. - Update map_tab.dart to use singleton instance of LocationTrackingService and streamline location tracking callbacks. - Modify ble_response_handler.dart to handle contact not found errors and improve error callback structure. - Enhance location_tracking_service.dart with retry logic for GPS position acquisition and initial position setting without broadcasting. - Update meshcore_ble_service.dart to track last contact for auto-recovery on errors. - Improve tile_cache_service.dart error messages and streamline tile download logic. - Add current GPS location insertion feature in direct_message_sheet.dart with permission checks. - Update pubspec.lock and pubspec.yaml to include integration_test dependency. - Add screenshot automation script for iOS and Android devices. - Create integration test driver for screenshot capturing.
This commit is contained in:
116
integration_test/helpers/screenshot_helper.dart
Normal file
116
integration_test/helpers/screenshot_helper.dart
Normal file
@@ -0,0 +1,116 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
/// Helper class for taking screenshots during integration tests
|
||||
class ScreenshotHelper {
|
||||
final IntegrationTestWidgetsFlutterBinding binding;
|
||||
final String outputDir;
|
||||
int _screenshotCounter = 0;
|
||||
|
||||
ScreenshotHelper(this.binding, {this.outputDir = 'screenshots'});
|
||||
|
||||
/// Take a screenshot with automatic numbering and description
|
||||
Future<void> takeScreenshot(
|
||||
WidgetTester tester,
|
||||
String description, {
|
||||
Duration? wait,
|
||||
}) async {
|
||||
// Wait for UI to settle
|
||||
await tester.pumpAndSettle(wait ?? const Duration(milliseconds: 500));
|
||||
|
||||
// Add extra delay for animations
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
// Increment counter
|
||||
_screenshotCounter++;
|
||||
|
||||
// Format filename: 01_description.png
|
||||
final filename =
|
||||
'${_screenshotCounter.toString().padLeft(2, '0')}_${_sanitizeFilename(description)}.png';
|
||||
|
||||
if (kDebugMode) {
|
||||
print('📸 Taking screenshot: $filename');
|
||||
}
|
||||
|
||||
// Take screenshot
|
||||
await binding.takeScreenshot(filename);
|
||||
}
|
||||
|
||||
/// Sanitize filename by removing special characters
|
||||
String _sanitizeFilename(String input) {
|
||||
return input
|
||||
.toLowerCase()
|
||||
.replaceAll(RegExp(r'[^\w\s-]'), '')
|
||||
.replaceAll(RegExp(r'[\s_]+'), '_')
|
||||
.replaceAll(RegExp(r'^-+|-+$'), '');
|
||||
}
|
||||
|
||||
/// Reset counter (useful for multiple test runs)
|
||||
void resetCounter() {
|
||||
_screenshotCounter = 0;
|
||||
}
|
||||
|
||||
/// Get current screenshot count
|
||||
int get screenshotCount => _screenshotCounter;
|
||||
|
||||
/// Create output directory if it doesn't exist
|
||||
static Future<void> ensureOutputDir(String path) async {
|
||||
final dir = Directory(path);
|
||||
if (!await dir.exists()) {
|
||||
await dir.create(recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension methods for easier screenshot taking
|
||||
extension ScreenshotTestExtension on WidgetTester {
|
||||
/// Wait for a specific widget to appear
|
||||
Future<void> waitFor(
|
||||
Finder finder, {
|
||||
Duration timeout = const Duration(seconds: 10),
|
||||
}) async {
|
||||
final end = DateTime.now().add(timeout);
|
||||
while (DateTime.now().isBefore(end)) {
|
||||
await pump();
|
||||
if (finder.evaluate().isNotEmpty) {
|
||||
return;
|
||||
}
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
}
|
||||
throw Exception('Widget not found: $finder');
|
||||
}
|
||||
|
||||
/// Tap and wait for navigation
|
||||
Future<void> tapAndSettle(Finder finder, {Duration? settleDuration}) async {
|
||||
await tap(finder);
|
||||
await pumpAndSettle(settleDuration ?? const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
/// Scroll until widget is visible
|
||||
Future<void> scrollUntilVisible(
|
||||
Finder finder,
|
||||
Finder scrollable, {
|
||||
double delta = 100,
|
||||
int maxScrolls = 50,
|
||||
}) async {
|
||||
int scrollCount = 0;
|
||||
while (finder.evaluate().isEmpty && scrollCount < maxScrolls) {
|
||||
await drag(scrollable, Offset(0, -delta));
|
||||
await pump(const Duration(milliseconds: 100));
|
||||
scrollCount++;
|
||||
}
|
||||
if (finder.evaluate().isEmpty) {
|
||||
throw Exception('Could not scroll to widget: $finder');
|
||||
}
|
||||
}
|
||||
|
||||
/// Fill text field and dismiss keyboard
|
||||
Future<void> enterTextAndDismiss(Finder finder, String text) async {
|
||||
await enterText(finder, text);
|
||||
await pump();
|
||||
await testTextInput.receiveAction(TextInputAction.done);
|
||||
await pumpAndSettle();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user