refactor(config): 服务地址改为 dev/prod 配置文件与单个环境开关
启动时按环回、局域网、公网顺序探测地址,换网络后会静默切到别处,排查 困难。改为代码内一个布尔开关选择环境,地址分别放在 dev_config.dart 与 prod_config.dart,不再探测;调试条改地址后直接重载,不再重新探测。 release 构建若仍是开发开关会启动即报错,避免线上包连开发机。
This commit is contained in:
1 parent
57f84c45bd
commit
a6d6b66d31
13 files changed
+101
-382
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import 'dart:async';
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
@@ -6,6 +6,8 @@ import 'package:shared_preferences_platform_interface/in_memory_shared_preferenc
|
||||
import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart';
|
||||
|
||||
import 'package:fruitshorts/core/config/app_config.dart';
|
||||
import 'package:fruitshorts/core/config/dev_config.dart';
|
||||
import 'package:fruitshorts/core/config/prod_config.dart';
|
||||
import 'package:fruitshorts/core/config/server_endpoint.dart';
|
||||
|
||||
void main() {
|
||||
@@ -35,11 +37,10 @@ void main() {
|
||||
expect(ServerEndpoint.normalize('http://'), isNull);
|
||||
});
|
||||
|
||||
test('should_prioritize_runtime_over_dart_define_over_default', () {
|
||||
test('should_prefer_valid_stored_url_over_build_default', () {
|
||||
expect(
|
||||
ServerEndpoint.resolve(
|
||||
stored: ' http://runtime.test:8081/ ',
|
||||
compiled: 'http://define.test:8081',
|
||||
fallback: 'http://default.test:8081',
|
||||
),
|
||||
'http://runtime.test:8081',
|
||||
@@ -47,173 +48,57 @@ void main() {
|
||||
expect(
|
||||
ServerEndpoint.resolve(
|
||||
stored: 'ftp://invalid',
|
||||
compiled: 'http://define.test:8081/',
|
||||
fallback: 'http://default.test:8081',
|
||||
fallback: 'http://default.test:8081/',
|
||||
),
|
||||
'http://define.test:8081',
|
||||
'http://default.test:8081',
|
||||
);
|
||||
expect(
|
||||
ServerEndpoint.resolve(
|
||||
stored: null,
|
||||
compiled: '',
|
||||
fallback: 'http://default.test:8081/',
|
||||
fallback: 'http://default.test:8081',
|
||||
),
|
||||
'http://default.test:8081',
|
||||
);
|
||||
});
|
||||
|
||||
test('should_use_the_configured_local_address_for_device_default', () {
|
||||
final uri = Uri.parse(AppConfig.devHostBaseUrl);
|
||||
expect(uri.scheme, 'http');
|
||||
expect(uri.host, isNotEmpty);
|
||||
expect(uri.port, 8081);
|
||||
expect(uri.path, isEmpty);
|
||||
test('should_pick_address_by_environment_switch', () {
|
||||
// 仓库里的开关默认指向开发环境。
|
||||
expect(AppConfig.useDevConfig, isTrue);
|
||||
expect(AppConfig.baseUrl, DevConfig.baseUrl);
|
||||
expect(AppConfig.apiBaseUrl, DevConfig.baseUrl);
|
||||
expect(Uri.parse(AppConfig.baseUrl).port, 8081);
|
||||
});
|
||||
|
||||
test('should_skip_probe_when_compiled_override_is_set', () async {
|
||||
const compiled = 'http://compiled.test:8081';
|
||||
var probeCalls = 0;
|
||||
test('should_keep_dev_and_prod_addresses_in_separate_files', () {
|
||||
final dev = Uri.parse(DevConfig.baseUrl);
|
||||
final prod = Uri.parse(ProdConfig.baseUrl);
|
||||
|
||||
await AppConfig.probeAndApplyBaseUrl(
|
||||
compiledOverride: compiled,
|
||||
probe: (_) async {
|
||||
probeCalls++;
|
||||
return true;
|
||||
},
|
||||
);
|
||||
|
||||
expect(probeCalls, 0);
|
||||
expect(AppConfig.apiBaseUrl, compiled);
|
||||
expect(dev.scheme, 'http');
|
||||
expect(dev.port, 8081);
|
||||
expect(dev.path, isEmpty);
|
||||
expect(prod.scheme, 'http');
|
||||
expect(prod.port, 8081);
|
||||
expect(prod.path, isEmpty);
|
||||
expect(DevConfig.baseUrl, isNot(ProdConfig.baseUrl));
|
||||
});
|
||||
|
||||
test('should_keep_runtime_endpoint_when_compiled_override_is_set', () async {
|
||||
const runtime = 'http://runtime.test:8081';
|
||||
const compiled = 'http://compiled.test:8081';
|
||||
var probeCalls = 0;
|
||||
AppConfig.applyRuntimeBaseUrl(runtime);
|
||||
test('should_prefer_runtime_override_over_environment_switch', () {
|
||||
AppConfig.applyRuntimeBaseUrl('http://runtime.test:8081');
|
||||
|
||||
await AppConfig.probeAndApplyBaseUrl(
|
||||
compiledOverride: compiled,
|
||||
probe: (_) async {
|
||||
probeCalls++;
|
||||
return true;
|
||||
},
|
||||
);
|
||||
|
||||
expect(probeCalls, 0);
|
||||
expect(AppConfig.apiBaseUrl, runtime);
|
||||
expect(AppConfig.apiBaseUrl, 'http://runtime.test:8081');
|
||||
expect(AppConfig.baseUrl, DevConfig.baseUrl);
|
||||
});
|
||||
|
||||
test('should_keep_probing_when_compiled_override_is_empty', () async {
|
||||
final attempts = <String>[];
|
||||
|
||||
await AppConfig.probeAndApplyBaseUrl(
|
||||
compiledOverride: '',
|
||||
probe: (baseUrl) async {
|
||||
attempts.add(baseUrl);
|
||||
return baseUrl == AppConfig.publicBaseUrl;
|
||||
},
|
||||
test('should_append_host_to_relative_media_paths', () {
|
||||
expect(AppConfig.mediaUrl(''), '');
|
||||
expect(
|
||||
AppConfig.mediaUrl('https://cdn.test/a.mp4'),
|
||||
'https://cdn.test/a.mp4',
|
||||
);
|
||||
|
||||
expect(attempts, [
|
||||
AppConfig.lanBaseUrl,
|
||||
AppConfig.devHostBaseUrl,
|
||||
AppConfig.publicBaseUrl,
|
||||
]);
|
||||
expect(AppConfig.apiBaseUrl, AppConfig.publicBaseUrl);
|
||||
});
|
||||
|
||||
test(
|
||||
'should_probe_all_candidates_in_parallel_before_applying_priority',
|
||||
() async {
|
||||
final attempts = <String>[];
|
||||
var active = 0;
|
||||
var maxActive = 0;
|
||||
final allStarted = Completer<void>();
|
||||
|
||||
final probing = AppConfig.probeAndApplyBaseUrl(
|
||||
fallbackBaseUrl: AppConfig.devHostBaseUrl,
|
||||
probe: (baseUrl) async {
|
||||
attempts.add(baseUrl);
|
||||
active++;
|
||||
if (active > maxActive) maxActive = active;
|
||||
if (active == 3) allStarted.complete();
|
||||
await allStarted.future;
|
||||
active--;
|
||||
return baseUrl == AppConfig.lanBaseUrl ||
|
||||
baseUrl == AppConfig.devHostBaseUrl;
|
||||
},
|
||||
);
|
||||
|
||||
await probing.timeout(const Duration(seconds: 1));
|
||||
|
||||
expect(attempts, [
|
||||
AppConfig.lanBaseUrl,
|
||||
AppConfig.devHostBaseUrl,
|
||||
AppConfig.publicBaseUrl,
|
||||
]);
|
||||
expect(maxActive, 3);
|
||||
expect(AppConfig.apiBaseUrl, AppConfig.lanBaseUrl);
|
||||
},
|
||||
);
|
||||
|
||||
test('should_probe_loopback_then_public_in_order', () async {
|
||||
final attempts = <String>[];
|
||||
|
||||
await AppConfig.probeAndApplyBaseUrl(
|
||||
fallbackBaseUrl: AppConfig.devHostBaseUrl,
|
||||
probe: (baseUrl) async {
|
||||
attempts.add(baseUrl);
|
||||
return baseUrl == AppConfig.publicBaseUrl;
|
||||
},
|
||||
expect(
|
||||
AppConfig.mediaUrl('/files/a.mp4'),
|
||||
'${AppConfig.apiBaseUrl}/files/a.mp4',
|
||||
);
|
||||
|
||||
expect(attempts, [
|
||||
AppConfig.lanBaseUrl,
|
||||
AppConfig.devHostBaseUrl,
|
||||
AppConfig.publicBaseUrl,
|
||||
]);
|
||||
expect(AppConfig.apiBaseUrl, AppConfig.publicBaseUrl);
|
||||
});
|
||||
|
||||
test('should_use_platform_default_when_all_probes_fail', () async {
|
||||
final attempts = <String>[];
|
||||
|
||||
await AppConfig.probeAndApplyBaseUrl(
|
||||
fallbackBaseUrl: AppConfig.devHostBaseUrl,
|
||||
probe: (baseUrl) async {
|
||||
attempts.add(baseUrl);
|
||||
return false;
|
||||
},
|
||||
);
|
||||
|
||||
expect(attempts, [
|
||||
AppConfig.lanBaseUrl,
|
||||
AppConfig.devHostBaseUrl,
|
||||
AppConfig.publicBaseUrl,
|
||||
]);
|
||||
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,
|
||||
AppConfig.lanBaseUrl,
|
||||
AppConfig.devHostBaseUrl,
|
||||
AppConfig.publicBaseUrl,
|
||||
]);
|
||||
expect(AppConfig.apiBaseUrl, custom);
|
||||
});
|
||||
|
||||
test('should_apply_stored_url_only_when_debug_is_enabled', () async {
|
||||
|
||||
Reference in new issue
Block a user