feat(mobile): in-app locale switching

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-19 05:00:11 +08:00
parent 955f9b13c1
commit 8f3966d7b5
8 changed files with 548 additions and 17 deletions
+42 -1
View File
@@ -8,6 +8,7 @@ import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:photo_live/app/locale_controller.dart';
import 'package:photo_live/core/api_client.dart';
import 'package:photo_live/core/session_store.dart';
import 'package:photo_live/l10n/app_localizations.dart';
@@ -35,13 +36,18 @@ void main() {
..httpClientAdapter = adapter,
);
Future<void> pumpHome(WidgetTester tester, ApiClient client) async {
Future<void> pumpHome(
WidgetTester tester,
ApiClient client, {
List<dynamic> extraOverrides = const <dynamic>[],
}) async {
await tester.pumpWidget(
ProviderScope(
// Task 9 起主壳含队列页(触达 sessionAccountProvider/TaskStore),
// 真实平台通道在测试环境挂起,必须注入替身。
overrides: [
...pageTestOverrides(session: store, client: client),
...extraOverrides,
],
child: MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
@@ -92,4 +98,39 @@ void main() {
expect(find.byType(LoginPage), findsOneWidget);
expect(find.byType(HomePage), findsNothing, reason: '主壳已出栈');
});
testWidgets('语言切换:底部弹层三选一 → 更新档位 + 持久化(P3 Task 10)',
(tester) async {
final adapter = FakeAdapter((_) => throw StateError('不应发起请求'));
final localeStore = FakeLocaleStore();
await pumpHome(
tester,
clientOf(adapter),
extraOverrides: [
localeSettingsProvider.overrideWith(
() => LocaleSettings(store: localeStore),
),
],
);
// 本 harness 的 MaterialApp 固定 en(live 全 App 重建在
// app/locale_test.dart 的 PhotoLiveApp 用例覆盖)。
expect(find.text('Language'), findsOneWidget);
expect(find.text('Follow system'), findsOneWidget, reason: '默认档位副标题');
await tester.tap(find.text('Language'));
await tester.pumpAndSettle();
// 弹层三选项(语言名以自身语言书写,跨 locale 不变)。
// 「Follow system」出现两次:主档 tile 副标题 + 弹层选项。
expect(find.text('Follow system'), findsNWidgets(2));
expect(find.text('中文'), findsOneWidget);
expect(find.text('English'), findsOneWidget);
await tester.tap(find.text('中文'));
await tester.pumpAndSettle();
expect(find.text('中文'), findsOneWidget, reason: '副标题更新为当前档位');
expect(localeStore.writes, ['zh'], reason: '选择写入 app.locale');
});
}