feat(auth): 登录页改为 ymb 品牌并支持后台配置背景图
This commit is contained in:
1 parent
22cc669bbe
commit
e7399fa3fd
24 files changed
+378
-188
No files matched your search
@@ -8,12 +8,14 @@ import 'package:shared_preferences_platform_interface/shared_preferences_async_p
|
||||
|
||||
import 'package:fruitshorts/core/data/remote/api_client.dart';
|
||||
import 'package:fruitshorts/core/data/remote/auth_api.dart';
|
||||
import 'package:fruitshorts/core/data/services/app_config_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/auth_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/auth_session_store.dart';
|
||||
import 'package:fruitshorts/core/platform/haptics.dart';
|
||||
import 'package:fruitshorts/l10n/app_localizations.dart';
|
||||
import 'package:fruitshorts/pages/auth/auth_view.dart';
|
||||
|
||||
import '../support/fake_app_config.dart';
|
||||
import '../support/fake_haptics.dart';
|
||||
import '../support/fake_http_adapter.dart';
|
||||
|
||||
@@ -71,6 +73,9 @@ Future<void> _pumpAuth(WidgetTester tester) async {
|
||||
MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<AuthController>.value(value: auth),
|
||||
ChangeNotifierProvider<AppConfigController>.value(
|
||||
value: await fakeAppConfigController(),
|
||||
),
|
||||
Provider<Haptics>.value(value: FakeHaptics()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
|
||||
@@ -8,12 +8,14 @@ import 'package:shared_preferences_platform_interface/shared_preferences_async_p
|
||||
|
||||
import 'package:fruitshorts/core/data/remote/api_client.dart';
|
||||
import 'package:fruitshorts/core/data/remote/auth_api.dart';
|
||||
import 'package:fruitshorts/core/data/services/app_config_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/auth_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/auth_session_store.dart';
|
||||
import 'package:fruitshorts/core/platform/haptics.dart';
|
||||
import 'package:fruitshorts/l10n/app_localizations.dart';
|
||||
import 'package:fruitshorts/pages/auth/auth_view.dart';
|
||||
|
||||
import '../support/fake_app_config.dart';
|
||||
import '../support/fake_haptics.dart';
|
||||
import '../support/fake_http_adapter.dart';
|
||||
|
||||
@@ -36,6 +38,9 @@ void main() {
|
||||
MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<AuthController>.value(value: auth),
|
||||
ChangeNotifierProvider<AppConfigController>.value(
|
||||
value: await fakeAppConfigController(),
|
||||
),
|
||||
Provider<Haptics>.value(value: FakeHaptics()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
|
||||
@@ -11,12 +11,14 @@ import 'package:shared_preferences_platform_interface/shared_preferences_async_p
|
||||
import 'package:fruitshorts/core/data/models/auth_session.dart';
|
||||
import 'package:fruitshorts/core/data/remote/auth_api.dart';
|
||||
import 'package:fruitshorts/core/data/remote/api_client.dart';
|
||||
import 'package:fruitshorts/core/data/services/app_config_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/auth_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/auth_session_store.dart';
|
||||
import 'package:fruitshorts/core/platform/haptics.dart';
|
||||
import 'package:fruitshorts/l10n/app_localizations.dart';
|
||||
import 'package:fruitshorts/pages/auth/auth_view.dart';
|
||||
|
||||
import '../support/fake_app_config.dart';
|
||||
import '../support/fake_http_adapter.dart';
|
||||
import '../support/fake_haptics.dart';
|
||||
|
||||
@@ -29,17 +31,17 @@ void main() {
|
||||
// 不打桩这个通道调用会一直等不到回复(提交按钮转圈、pumpAndSettle 超时)。
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(
|
||||
const MethodChannel('com.stormg.lumadrama/device'),
|
||||
(call) async => call.method == 'region' ? 'ID' : null,
|
||||
);
|
||||
const MethodChannel('com.stormg.lumadrama/device'),
|
||||
(call) async => call.method == 'region' ? 'ID' : null,
|
||||
);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(
|
||||
const MethodChannel('com.stormg.lumadrama/device'),
|
||||
null,
|
||||
);
|
||||
const MethodChannel('com.stormg.lumadrama/device'),
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
Future<void> pumpAuthPage(
|
||||
@@ -65,6 +67,9 @@ void main() {
|
||||
MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<AuthController>.value(value: auth),
|
||||
ChangeNotifierProvider<AppConfigController>.value(
|
||||
value: await fakeAppConfigController(),
|
||||
),
|
||||
Provider<Haptics>.value(value: haptics ?? FakeHaptics()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
@@ -212,7 +217,7 @@ void main() {
|
||||
) async {
|
||||
await pumpAuthPage(tester);
|
||||
|
||||
expect(find.text('FruitShorts'), findsOneWidget);
|
||||
expect(find.text('ymb'), findsNothing);
|
||||
expect(find.text('Short dramas made for Indonesia'), findsOneWidget);
|
||||
final email = tester.widget<TextField>(find.byKey(const Key('auth-email')));
|
||||
final password = tester.widget<TextField>(
|
||||
|
||||
@@ -9,13 +9,16 @@ import 'package:shared_preferences_platform_interface/shared_preferences_async_p
|
||||
import 'package:fruitshorts/core/data/models/auth_session.dart';
|
||||
import 'package:fruitshorts/core/data/remote/api_client.dart';
|
||||
import 'package:fruitshorts/core/data/remote/auth_api.dart';
|
||||
import 'package:fruitshorts/core/data/services/app_config_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/auth_controller.dart';
|
||||
import 'package:fruitshorts/core/data/services/auth_session_store.dart';
|
||||
import 'package:fruitshorts/core/platform/haptics.dart';
|
||||
import 'package:fruitshorts/core/theme/app_colors.dart';
|
||||
import 'package:fruitshorts/core/widgets/remote_image.dart';
|
||||
import 'package:fruitshorts/l10n/app_localizations.dart';
|
||||
import 'package:fruitshorts/pages/auth/auth_view.dart';
|
||||
|
||||
import '../support/fake_app_config.dart';
|
||||
import '../support/fake_haptics.dart';
|
||||
import '../support/fake_http_adapter.dart';
|
||||
|
||||
@@ -29,6 +32,7 @@ void main() {
|
||||
WidgetTester tester, {
|
||||
AuthApi? api,
|
||||
FakeHaptics? haptics,
|
||||
String loginBackgroundUrl = '',
|
||||
bool openEmail = true,
|
||||
bool asRoute = false,
|
||||
}) async {
|
||||
@@ -44,10 +48,14 @@ void main() {
|
||||
),
|
||||
AuthSessionStore(),
|
||||
);
|
||||
final appConfig = await fakeAppConfigController(
|
||||
loginBackgroundUrl: loginBackgroundUrl,
|
||||
);
|
||||
await tester.pumpWidget(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<AuthController>.value(value: auth),
|
||||
ChangeNotifierProvider<AppConfigController>.value(value: appConfig),
|
||||
Provider<Haptics>.value(value: haptics ?? FakeHaptics()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
@@ -76,11 +84,8 @@ void main() {
|
||||
await pumpAuthPage(tester, openEmail: false);
|
||||
|
||||
expect(find.byKey(const Key('auth-landing')), findsOneWidget);
|
||||
expect(find.text('FruitShorts'), findsOneWidget);
|
||||
final brand = tester.widget<Text>(find.text('FruitShorts'));
|
||||
expect(brand.style?.fontSize, 26);
|
||||
expect(brand.style?.fontWeight, FontWeight.w700);
|
||||
expect(brand.style?.letterSpacing, 2);
|
||||
// 落地页只留图标,不再显示品牌文字。
|
||||
expect(find.text('ymb'), findsNothing);
|
||||
expect(
|
||||
tester.getSize(find.byKey(const Key('auth-brand-logo'))),
|
||||
const Size(88, 88),
|
||||
@@ -136,10 +141,7 @@ void main() {
|
||||
final email = tester.widget<TextField>(
|
||||
find.byKey(const Key('auth-email')),
|
||||
);
|
||||
expect(
|
||||
email.decoration?.fillColor,
|
||||
Colors.white.withValues(alpha: 0.05),
|
||||
);
|
||||
expect(email.decoration?.fillColor, Colors.white.withValues(alpha: 0.05));
|
||||
expect(email.style?.color, AppColors.onSurface);
|
||||
expect(email.style?.fontSize, 15);
|
||||
expect(email.cursorColor, AppColors.brandRed);
|
||||
@@ -182,37 +184,63 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('should_use_backend_login_background_when_configured', (
|
||||
tester,
|
||||
) async {
|
||||
await pumpAuthPage(
|
||||
tester,
|
||||
openEmail: false,
|
||||
loginBackgroundUrl: '/files/login_bg/bg.jpg',
|
||||
);
|
||||
|
||||
final backdrop = tester.widget<RemoteImage>(
|
||||
find.byKey(const Key('auth-poster-backdrop')),
|
||||
);
|
||||
expect(backdrop.path, '/files/login_bg/bg.jpg');
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'should_show_app_logo_lower_on_the_page_when_landing_opens',
|
||||
'should_fall_back_to_bundled_login_background_when_not_configured',
|
||||
(tester) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
await pumpAuthPage(tester, openEmail: false);
|
||||
|
||||
final image = tester.widget<Image>(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('auth-brand-logo')),
|
||||
matching: find.byType(Image),
|
||||
),
|
||||
final backdrop = tester.widget<RemoteImage>(
|
||||
find.byKey(const Key('auth-poster-backdrop')),
|
||||
);
|
||||
expect(backdrop.path, isEmpty);
|
||||
// 兜底图是我们塞给 RemoteImage 的 fallbackWidget,用 auth-poster-default 定位。
|
||||
expect(
|
||||
(image.image as AssetImage).assetName,
|
||||
'assets/icon/fruitshorts.png',
|
||||
);
|
||||
// 新版落地页用三等分 Spacer 排版,Logo 居中且落在两个入口按钮上方。
|
||||
final logo = find.byKey(const Key('auth-brand-logo'));
|
||||
expect(tester.getCenter(logo).dx, closeTo(195, 0.1));
|
||||
expect(
|
||||
tester.getBottomLeft(logo).dy,
|
||||
lessThan(
|
||||
tester.getTopLeft(find.byKey(const Key('auth-entry-phone'))).dy,
|
||||
),
|
||||
find.byKey(const Key('auth-poster-default')),
|
||||
findsOneWidget,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('should_show_app_logo_lower_on_the_page_when_landing_opens', (
|
||||
tester,
|
||||
) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
await pumpAuthPage(tester, openEmail: false);
|
||||
|
||||
final image = tester.widget<Image>(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('auth-brand-logo')),
|
||||
matching: find.byType(Image),
|
||||
),
|
||||
);
|
||||
expect((image.image as AssetImage).assetName, 'assets/icon/ymb.png');
|
||||
// 新版落地页用三等分 Spacer 排版,Logo 居中且落在两个入口按钮上方。
|
||||
final logo = find.byKey(const Key('auth-brand-logo'));
|
||||
expect(tester.getCenter(logo).dx, closeTo(195, 0.1));
|
||||
expect(
|
||||
tester.getBottomLeft(logo).dy,
|
||||
lessThan(tester.getTopLeft(find.byKey(const Key('auth-entry-phone'))).dy),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('should_render_40px_back_button_when_page_is_pushed', (
|
||||
tester,
|
||||
) async {
|
||||
@@ -335,9 +363,7 @@ void main() {
|
||||
);
|
||||
expect(
|
||||
tester
|
||||
.widget<GestureDetector>(
|
||||
find.byKey(const Key('auth-mode-sign-up')),
|
||||
)
|
||||
.widget<GestureDetector>(find.byKey(const Key('auth-mode-sign-up')))
|
||||
.onTap,
|
||||
isNull,
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user