계정 정보 다이얼로그 추가 및 전체 목록 페치 개선
This commit is contained in:
196
test/widgets/app_shell_test.dart
Normal file
196
test/widgets/app_shell_test.dart
Normal file
@@ -0,0 +1,196 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart' as lucide;
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
|
||||
import 'package:superport_v2/core/constants/app_sections.dart';
|
||||
import 'package:superport_v2/core/permissions/permission_manager.dart';
|
||||
import 'package:superport_v2/core/theme/superport_shad_theme.dart';
|
||||
import 'package:superport_v2/core/theme/theme_controller.dart';
|
||||
import 'package:superport_v2/core/services/token_storage.dart';
|
||||
import 'package:superport_v2/features/auth/application/auth_service.dart';
|
||||
import 'package:superport_v2/features/auth/domain/entities/auth_permission.dart';
|
||||
import 'package:superport_v2/features/auth/domain/entities/auth_session.dart';
|
||||
import 'package:superport_v2/features/auth/domain/entities/authenticated_user.dart';
|
||||
import 'package:superport_v2/features/auth/domain/entities/login_request.dart';
|
||||
import 'package:superport_v2/features/auth/domain/repositories/auth_repository.dart';
|
||||
import 'package:superport_v2/widgets/app_shell.dart';
|
||||
|
||||
void main() {
|
||||
setUp(() {
|
||||
GetIt.I.reset();
|
||||
});
|
||||
|
||||
testWidgets('계정 버튼을 누르면 계정 정보 다이얼로그가 표시된다', (tester) async {
|
||||
final session = _buildSession();
|
||||
final authService = _createAuthService(session);
|
||||
GetIt.I.registerSingleton<AuthService>(authService);
|
||||
addTearDown(authService.dispose);
|
||||
await authService.login(
|
||||
const LoginRequest(identifier: 'user@example.com', password: 'secret'),
|
||||
);
|
||||
|
||||
await _pumpAppShell(tester);
|
||||
|
||||
await tester.tap(find.byIcon(lucide.LucideIcons.userRound));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('계정 정보'), findsOneWidget);
|
||||
expect(find.text('김승인'), findsWidgets);
|
||||
expect(find.text('E2025001'), findsOneWidget);
|
||||
expect(find.text('물류팀'), findsOneWidget);
|
||||
expect(find.textContaining('/approvals'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('다이얼로그에서 로그아웃을 누르면 세션이 초기화되고 로그인 화면으로 이동한다', (tester) async {
|
||||
final session = _buildSession();
|
||||
final authService = _createAuthService(session);
|
||||
GetIt.I.registerSingleton<AuthService>(authService);
|
||||
addTearDown(authService.dispose);
|
||||
await authService.login(
|
||||
const LoginRequest(identifier: 'user@example.com', password: 'secret'),
|
||||
);
|
||||
|
||||
await _pumpAppShell(tester);
|
||||
|
||||
expect(authService.session, isNotNull);
|
||||
|
||||
await tester.tap(find.byIcon(lucide.LucideIcons.userRound));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.text('로그아웃'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(authService.session, isNull);
|
||||
expect(find.text('로그인 페이지'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _pumpAppShell(WidgetTester tester) async {
|
||||
final themeController = ThemeController();
|
||||
final permissionManager = PermissionManager();
|
||||
final router = GoRouter(
|
||||
initialLocation: dashboardRoutePath,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: loginRoutePath,
|
||||
builder: (context, state) => const _LoginPlaceholder(),
|
||||
),
|
||||
ShellRoute(
|
||||
builder: (context, state, child) =>
|
||||
AppShell(currentLocation: state.uri.toString(), child: child),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: dashboardRoutePath,
|
||||
builder: (context, state) => const _DashboardPlaceholder(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
addTearDown(themeController.dispose);
|
||||
addTearDown(permissionManager.dispose);
|
||||
addTearDown(router.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
PermissionScope(
|
||||
manager: permissionManager,
|
||||
child: ThemeControllerScope(
|
||||
controller: themeController,
|
||||
child: ShadApp.router(
|
||||
routerConfig: router,
|
||||
theme: SuperportShadTheme.light(),
|
||||
darkTheme: SuperportShadTheme.dark(),
|
||||
debugShowCheckedModeBanner: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
AuthSession _buildSession() {
|
||||
return AuthSession(
|
||||
accessToken: 'access-token',
|
||||
refreshToken: 'refresh-token',
|
||||
expiresAt: DateTime.parse('2025-10-21T09:00:00Z'),
|
||||
user: const AuthenticatedUser(
|
||||
id: 7,
|
||||
name: '김승인',
|
||||
employeeNo: 'E2025001',
|
||||
email: 'approver@example.com',
|
||||
primaryGroupId: 3,
|
||||
primaryGroupName: '물류팀',
|
||||
),
|
||||
permissions: const [
|
||||
AuthPermission(resource: '/dashboard', actions: ['read']),
|
||||
AuthPermission(resource: '/approvals', actions: ['read', 'update']),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
AuthService _createAuthService(AuthSession session) {
|
||||
final repository = _FakeAuthRepository(session);
|
||||
final tokenStorage = _MemoryTokenStorage();
|
||||
return AuthService(repository: repository, tokenStorage: tokenStorage);
|
||||
}
|
||||
|
||||
class _FakeAuthRepository implements AuthRepository {
|
||||
_FakeAuthRepository(this.session);
|
||||
|
||||
final AuthSession session;
|
||||
|
||||
@override
|
||||
Future<AuthSession> login(LoginRequest request) async => session;
|
||||
|
||||
@override
|
||||
Future<AuthSession> refresh(String refreshToken) async => session;
|
||||
}
|
||||
|
||||
class _MemoryTokenStorage implements TokenStorage {
|
||||
String? _access;
|
||||
String? _refresh;
|
||||
|
||||
@override
|
||||
Future<void> clear() async {
|
||||
_access = null;
|
||||
_refresh = null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> readAccessToken() async => _access;
|
||||
|
||||
@override
|
||||
Future<String?> readRefreshToken() async => _refresh;
|
||||
|
||||
@override
|
||||
Future<void> writeAccessToken(String? token) async {
|
||||
_access = token;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeRefreshToken(String? token) async {
|
||||
_refresh = token;
|
||||
}
|
||||
}
|
||||
|
||||
class _DashboardPlaceholder extends StatelessWidget {
|
||||
const _DashboardPlaceholder();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Scaffold(body: Center(child: Text('대시보드 본문')));
|
||||
}
|
||||
}
|
||||
|
||||
class _LoginPlaceholder extends StatelessWidget {
|
||||
const _LoginPlaceholder();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Scaffold(body: Center(child: Text('로그인 페이지')));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user