feat(flutter): 增加 debug 服务地址编辑器

This commit is contained in:
Zhou Weidong committed 2026-10-20 18:23:44 +08:00
1 parent eab5d3e230
commit c259b0b543
9 files changed
+298 -5

No files matched your search

+17
View File
@@ -113,6 +113,22 @@ void main() {
expect(AppConfig.apiBaseUrl, AppConfig.devHostBaseUrl);
});
test('should_probe_explicit_runtime_endpoint_first', () async {
const custom = 'http://custom.test:8081';
final attempts = <String>[];
AppConfig.applyRuntimeBaseUrl(custom);
await AppConfig.probeAndApplyBaseUrl(
probe: (baseUrl) async {
attempts.add(baseUrl);
return baseUrl == custom;
},
);
expect(attempts, [custom]);
expect(AppConfig.apiBaseUrl, custom);
});
test('should_apply_stored_url_only_when_debug_is_enabled', () async {
SharedPreferencesAsyncPlatform.instance =
InMemorySharedPreferencesAsync.withData({
@@ -139,6 +155,7 @@ void main() {
await SharedPreferencesAsync().getString(ServerEndpoint.preferenceKey),
'http://192.168.31.187:8081',
);
expect(AppConfig.apiBaseUrl, 'http://192.168.31.187:8081');
await ServerEndpoint.clear();
expect(
@@ -137,6 +137,10 @@ void main() {
expect(find.text('Retry'), findsOneWidget);
expect(find.byKey(const Key('catalog-debug-endpoint')), findsOneWidget);
expect(find.byKey(const Key('catalog-debug-error')), findsOneWidget);
expect(
find.byKey(const Key('catalog-debug-endpoint-edit')),
findsOneWidget,
);
expect(find.textContaining('discover feed unavailable'), findsOneWidget);
});
+110
View File
@@ -1,11 +1,14 @@
// Author: fruit.com.cn
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:fruitshorts/core/config/app_config.dart';
import 'package:fruitshorts/core/data/services/catalog_retry.dart';
import 'package:fruitshorts/core/theme/app_colors.dart';
import 'package:fruitshorts/core/widgets/catalog_endpoint_editor.dart';
import 'package:fruitshorts/l10n/app_localizations.dart';
import 'package:fruitshorts/pages/home/home_view.dart';
@@ -25,6 +28,7 @@ void main() {
body: HomeFailureView(
error: 'SocketException: Connection refused',
onRetry: () {},
onEditEndpoint: () {},
),
),
),
@@ -45,6 +49,10 @@ void main() {
expect(error.style?.fontSize, 12);
expect(error.style?.color, AppColors.subtle);
expect(error.maxLines, 2);
expect(
find.byKey(const Key('catalog-debug-endpoint-edit')),
findsOneWidget,
);
});
test('should_probe_before_reloading_catalog', () async {
@@ -57,4 +65,106 @@ void main() {
expect(steps, ['probe', 'load']);
});
testWidgets('should_save_probe_and_reload_after_valid_endpoint', (
tester,
) async {
AppConfig.applyRuntimeBaseUrl('http://127.0.0.1:8081');
final steps = <String>[];
await _pumpEndpointEditor(
tester,
save: (value) async {
steps.add('save:$value');
return true;
},
probe: () async => steps.add('probe'),
reload: () async => steps.add('load'),
);
expect(
tester
.widget<TextField>(
find.byKey(const Key('catalog-debug-endpoint-input')),
)
.controller
?.text,
'http://127.0.0.1:8081',
);
expect(
find.byKey(const Key('catalog-debug-endpoint-hint')),
findsOneWidget,
);
await tester.enterText(
find.byKey(const Key('catalog-debug-endpoint-input')),
'http://10.0.0.8:8081///',
);
await tester.tap(find.byKey(const Key('catalog-debug-endpoint-save')));
await tester.pumpAndSettle();
expect(steps, ['save:http://10.0.0.8:8081', 'probe', 'load']);
});
testWidgets('should_reject_invalid_endpoint_without_saving', (tester) async {
var saves = 0;
var probes = 0;
var loads = 0;
await _pumpEndpointEditor(
tester,
save: (_) async {
saves++;
return true;
},
probe: () async => probes++,
reload: () async => loads++,
);
await tester.enterText(
find.byKey(const Key('catalog-debug-endpoint-input')),
'not a valid url',
);
await tester.tap(find.byKey(const Key('catalog-debug-endpoint-save')));
await tester.pump();
expect(
find.byKey(const Key('catalog-debug-endpoint-error')),
findsOneWidget,
);
expect(
find.byKey(const Key('catalog-debug-endpoint-input')),
findsOneWidget,
);
expect(saves, 0);
expect(probes, 0);
expect(loads, 0);
});
}
Future<void> _pumpEndpointEditor(
WidgetTester tester, {
required Future<bool> Function(String value) save,
required Future<void> Function() probe,
required Future<void> Function() reload,
}) async {
await tester.pumpWidget(
MaterialApp(
home: Builder(
builder: (context) => Scaffold(
body: TextButton(
key: const Key('open-endpoint-editor'),
onPressed: () => unawaited(
showCatalogEndpointEditor(
context,
save: save,
probe: probe,
reload: reload,
),
),
child: const Text('open'),
),
),
),
),
);
await tester.tap(find.byKey(const Key('open-endpoint-editor')));
await tester.pumpAndSettle();
}