Refactor H5 line management and cache handling in WebView app

- Introduced shared_preferences for initial H5 cache management.
- Added methods to clear H5 caches and probe line availability.
- Enhanced error handling for line loading and switching.
- Removed openim_common package and its configurations.
- Updated widget tests to reflect changes in H5 line handling and URL management.
This commit is contained in:
Booker
2026-05-29 17:56:55 +07:00
parent 131df57dfe
commit a1e7b3e52c
11 changed files with 881 additions and 288 deletions

View File

@@ -11,108 +11,71 @@ void main() {
);
});
test('loads the configured H5 root URL without shell URL params', () {
const logo = 'data:image/png;base64,abc+/=';
final uri = Uri.parse(
AppConfig.homeUrl(appName: 'Shell Test', appLogo: logo),
);
expect(uri.scheme, 'https');
expect(uri.host, 'h5-test.imharry.work');
expect(uri.path, '/');
expect(uri.queryParameters.containsKey('flutter_shell'), isFalse);
expect(uri.queryParameters.containsKey('shell_app_name'), isFalse);
expect(uri.queryParameters.containsKey('shell_app_logo'), isFalse);
expect(uri.queryParameters.containsKey('shell_cache_bust'), isFalse);
expect(uri.toString(), isNot(contains('%25')));
expect(Uri.splitQueryString(uri.fragment).containsKey('shell_app_logo'),
isFalse);
});
test('exposes configured H5 URLs as Flutter shell lines', () {
test('exposes bootstrap H5 URL as Flutter shell lines', () {
final lines = AppConfig.h5Lines;
expect(lines, isNotEmpty);
expect(lines.first.label, '线路1');
expect(lines.first.url, AppConfig.homeUrl(lineIndex: 0));
expect(Uri.parse(lines.first.url).host, 'h5-test.imharry.work');
expect(Uri.parse(lines.first.url).scheme, 'https');
expect(Uri.parse(lines.first.url).path, '/');
});
test('falls back to the first H5 line for invalid line indexes', () {
expect(AppConfig.homeUrl(lineIndex: -1), AppConfig.h5Lines.first.url);
expect(AppConfig.homeUrl(lineIndex: 99), AppConfig.h5Lines.first.url);
test('uses fixed client config query parameters', () {
expect(AppConfig.clientConfigQueryPayload, {
'device': 'h5',
'serialNo': 'h5-domain',
});
expect(
AppConfig.clientConfigQueryUris.first.path,
'/client_config/query',
);
});
test('matches runtime URLs back to their Flutter shell line', () {
final lineUrl = AppConfig.h5Lines.first.url;
test('splits client config resourceUrl into indexed H5 lines', () {
final lines = AppConfig.h5LinesFromResourceUrl(
'line-one.example\nhttps://line-two.example/app\n\nline-three.example',
);
expect(AppConfig.lineIndexForUrl('${lineUrl}login'), 0);
expect(lines.map((line) => line.label), ['线路1', '线路2', '线路3']);
expect(Uri.parse(lines[0].url).host, 'line-one.example');
expect(Uri.parse(lines[1].url).host, 'line-two.example');
expect(Uri.parse(lines[1].url).path, '/app');
expect(Uri.parse(lines[2].url).host, 'line-three.example');
});
test('splits literal backslash-n resourceUrl values', () {
final lines = AppConfig.h5LinesFromResourceUrl(
r'line-one.example\n*.line-two.example\nline-three.example',
wildcardFactory: () => 'abcdefghijklmnop',
);
expect(lines.map((line) => line.label), ['线路1', '线路2', '线路3']);
expect(Uri.parse(lines[0].url).host, 'line-one.example');
expect(Uri.parse(lines[1].url).host, 'abcdefghijklmnop.line-two.example');
expect(Uri.parse(lines[2].url).host, 'line-three.example');
});
test('expands wildcard H5 domains with a 16 character label', () {
final lines = AppConfig.h5LinesFromResourceUrl(
'*.albzyuxq.vip',
wildcardFactory: () => 'abcdefghijklmnop',
);
final host = Uri.parse(lines.single.url).host;
expect(host, 'abcdefghijklmnop.albzyuxq.vip');
expect(host.split('.').first.length, 16);
});
test('detects only H5 login routes for shell line switch display', () {
expect(AppConfig.isLoginPageUrl('https://line-one.example/login'), isTrue);
expect(
AppConfig.isLoginPageUrl('https://h5-test.imharry.work/login'), isTrue);
expect(AppConfig.isLoginPageUrl('https://h5-test.imharry.work/app/login'),
isTrue);
expect(AppConfig.isLoginPageUrl('https://h5-test.imharry.work/#/login'),
isTrue);
expect(AppConfig.isLoginPageUrl('https://h5-test.imharry.work/'), isFalse);
expect(AppConfig.isLoginPageUrl('https://h5-test.imharry.work/contact'),
isFalse);
expect(AppConfig.isLoginPageUrl('https://h5-test.imharry.work/getCode'),
isFalse);
});
test('refreshes an H5 route URL without adding branding to the URL', () {
final uri = Uri.parse(
AppConfig.withFreshShellParams(
'https://h5-test.imharry.work/login?from=runtime&shell_app_name=Old'
'&flutter_shell=1&shell_cache_bust=1#shell_app_logo=old',
),
);
expect(uri.path, '/login');
expect(uri.queryParameters['from'], 'runtime');
expect(uri.queryParameters.containsKey('flutter_shell'), isFalse);
expect(uri.queryParameters.containsKey('shell_app_name'), isFalse);
expect(uri.queryParameters.containsKey('shell_app_logo'), isFalse);
expect(uri.queryParameters.containsKey('shell_cache_bust'), isFalse);
expect(Uri.splitQueryString(uri.fragment).containsKey('shell_app_logo'),
isFalse);
});
test('keeps H5 runtime URLs untouched during shell routing', () {
final uri = Uri.parse(
AppConfig.canonicalizeMainFrameUrl(
'https://line-two.example/login?shell_app_name=Old'
'&flutter_shell=1#shell_app_logo=old',
),
);
expect(uri.host, 'line-two.example');
expect(uri.path, '/login');
expect(uri.queryParameters['shell_app_name'], 'Old');
expect(uri.queryParameters['flutter_shell'], '1');
expect(Uri.splitQueryString(uri.fragment).containsKey('shell_app_logo'),
isTrue);
});
test('does not rewrite H5 main-frame URLs for line switching', () {
final uri = Uri.parse(
AppConfig.canonicalizeMainFrameUrl(
'https://h5-test.imharry.work/login?from=runtime'
'&shell_app_name=Old#shell_app_logo=old',
),
);
expect(uri.scheme, 'https');
expect(uri.host, 'h5-test.imharry.work');
expect(uri.path, '/login');
expect(uri.queryParameters['from'], 'runtime');
expect(uri.queryParameters['shell_app_name'], 'Old');
expect(Uri.splitQueryString(uri.fragment).containsKey('shell_app_logo'),
isTrue);
expect(AppConfig.shouldRewriteMainFrameUrl(uri.toString()), isFalse);
AppConfig.isLoginPageUrl('https://line-one.example/app/login'), isTrue);
expect(
AppConfig.isLoginPageUrl('https://line-one.example/#/login'), isTrue);
expect(AppConfig.isLoginPageUrl('https://line-one.example/'), isFalse);
expect(
AppConfig.isLoginPageUrl('https://line-one.example/contact'), isFalse);
expect(
AppConfig.isLoginPageUrl('https://line-one.example/getCode'), isFalse);
});
}