forked from baron/baron-sso
프로필 자동저장 제거 및 명시적 저장 UX 개선
This commit is contained in:
120
userfront/test/profile_page_edit_flow_test.dart
Normal file
120
userfront/test/profile_page_edit_flow_test.dart
Normal file
@@ -0,0 +1,120 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:userfront/features/profile/data/models/user_profile_model.dart';
|
||||
import 'package:userfront/features/profile/domain/notifiers/profile_notifier.dart';
|
||||
import 'package:userfront/features/profile/presentation/pages/profile_page.dart';
|
||||
|
||||
// Mocking the profile notifier
|
||||
class MockProfileNotifier extends ProfileNotifier {
|
||||
UserProfile? _profile;
|
||||
bool updateCalled = false;
|
||||
String? updatedName;
|
||||
|
||||
@override
|
||||
Future<UserProfile?> build() async {
|
||||
_profile = UserProfile(
|
||||
id: 'test-id',
|
||||
email: 'test@example.com',
|
||||
name: 'Original Name',
|
||||
phone: '01012345678',
|
||||
department: 'Dev',
|
||||
affiliationType: 'employee',
|
||||
companyCode: 'C100',
|
||||
);
|
||||
return _profile;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<UserProfile?> loadProfile() async {
|
||||
state = const AsyncValue.loading();
|
||||
state = AsyncValue.data(_profile);
|
||||
return _profile;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateProfile({String? name, String? phone, String? department}) async {
|
||||
updateCalled = true;
|
||||
updatedName = name;
|
||||
_profile = _profile!.copyWith(
|
||||
name: name ?? _profile!.name,
|
||||
phone: phone ?? _profile!.phone,
|
||||
department: department ?? _profile!.department,
|
||||
);
|
||||
state = AsyncValue.data(_profile);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('ProfilePage explicit save button UX flow (Edit -> Cancel -> Edit -> Save)', (tester) async {
|
||||
final recordedErrors = <FlutterErrorDetails>[];
|
||||
final previousOnError = FlutterError.onError;
|
||||
FlutterError.onError = (details) {
|
||||
final text = details.exceptionAsString();
|
||||
if (text.contains('A RenderFlex overflowed')) {
|
||||
return;
|
||||
}
|
||||
recordedErrors.add(details);
|
||||
};
|
||||
addTearDown(() {
|
||||
FlutterError.onError = previousOnError;
|
||||
});
|
||||
|
||||
tester.view.physicalSize = const Size(1920, 1080);
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
|
||||
final mockNotifier = MockProfileNotifier();
|
||||
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
profileProvider.overrideWith(() => mockNotifier),
|
||||
],
|
||||
child: const MaterialApp(
|
||||
home: Scaffold(body: ProfilePage()),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 1. Entering edit mode
|
||||
final editButton = find.byKey(const Key('profile-name-edit-button'));
|
||||
expect(editButton, findsOneWidget);
|
||||
await tester.tap(editButton);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final inputField = find.byKey(const Key('profile-name-input'));
|
||||
expect(inputField, findsOneWidget);
|
||||
|
||||
// 2. Testing cancel flow
|
||||
await tester.enterText(inputField, 'Changed Name');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final cancelButton = find.byKey(const Key('profile-name-cancel-button'));
|
||||
await tester.tap(cancelButton);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// After cancellation, the field should be read-only again.
|
||||
expect(find.byKey(const Key('profile-name-input')), findsNothing);
|
||||
// Find text could be part of ListTile
|
||||
expect(find.text('Original Name'), findsWidgets);
|
||||
|
||||
// 3. Re-enter edit mode and explicitly save
|
||||
await tester.tap(find.byKey(const Key('profile-name-edit-button')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.enterText(find.byKey(const Key('profile-name-input')), 'Saved Name');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final saveButton = find.byKey(const Key('profile-name-save-button'));
|
||||
await tester.tap(saveButton);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Verify the mock received the update
|
||||
expect(mockNotifier.updateCalled, isTrue);
|
||||
expect(mockNotifier.updatedName, 'Saved Name');
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user