import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:mockito/annotations.dart'; import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; import 'package:superport/domain/usecases/auth/login_usecase.dart'; import 'package:superport/domain/usecases/base_usecase.dart'; import 'package:superport/services/auth_service.dart'; import 'package:superport/data/models/auth/login_request.dart'; import 'package:superport/data/models/auth/login_response.dart'; import 'package:superport/data/models/auth/auth_user.dart'; import 'package:superport/core/utils/error_handler.dart'; import 'login_usecase_test.mocks.dart'; @GenerateMocks([AuthService]) void main() { late LoginUseCase loginUseCase; late MockAuthService mockAuthService; setUp(() { mockAuthService = MockAuthService(); loginUseCase = LoginUseCase(mockAuthService); }); group('LoginUseCase', () { const tEmail = 'test@example.com'; const tPassword = 'password123!'; const tInvalidEmail = 'invalid-email'; const tEmptyPassword = ''; final tLoginRequest = LoginRequest( email: tEmail, password: tPassword, ); final tLoginResponse = LoginResponse( accessToken: 'test_access_token', refreshToken: 'test_refresh_token', tokenType: 'Bearer', expiresIn: 3600, user: AuthUser( id: 1, username: 'testuser', email: tEmail, name: 'Test User', role: 'U', ), ); test('로그인 성공 시 Right(LoginResponse) 반환', () async { // arrange when(mockAuthService.login(any)) .thenAnswer((_) async => tLoginResponse); // act final result = await loginUseCase( LoginParams(email: tEmail, password: tPassword), ); // assert expect(result, Right(tLoginResponse)); verify(mockAuthService.login(argThat( predicate((req) => req.email == tEmail && req.password == tPassword), ))).called(1); verifyNoMoreInteractions(mockAuthService); }); test('잘못된 이메일 형식 입력 시 ValidationFailure 반환', () async { // act final result = await loginUseCase( LoginParams(email: tInvalidEmail, password: tPassword), ); // assert expect(result.isLeft(), true); result.fold( (failure) { expect(failure, isA()); expect(failure.message, '올바른 이메일 형식이 아닙니다.'); }, (_) => fail('Should return failure'), ); verifyNever(mockAuthService.login(any)); }); test('빈 비밀번호 입력 시 ValidationFailure 반환', () async { // act final result = await loginUseCase( LoginParams(email: tEmail, password: tEmptyPassword), ); // assert expect(result.isLeft(), true); result.fold( (failure) { expect(failure, isA()); expect(failure.message, '비밀번호를 입력해주세요.'); }, (_) => fail('Should return failure'), ); verifyNever(mockAuthService.login(any)); }); test('401 에러 시 AuthFailure 반환', () async { // arrange final dioError = DioException( requestOptions: RequestOptions(path: '/login'), response: Response( requestOptions: RequestOptions(path: '/login'), statusCode: 401, ), type: DioExceptionType.badResponse, ); when(mockAuthService.login(any)).thenThrow(dioError); // act final result = await loginUseCase( LoginParams(email: tEmail, password: tPassword), ); // assert expect(result.isLeft(), true); result.fold( (failure) { expect(failure, isA()); expect(failure.message, contains('인증')); }, (_) => fail('Should return failure'), ); }); test('네트워크 타임아웃 시 NetworkFailure 반환', () async { // arrange final dioError = DioException( requestOptions: RequestOptions(path: '/login'), type: DioExceptionType.connectionTimeout, ); when(mockAuthService.login(any)).thenThrow(dioError); // act final result = await loginUseCase( LoginParams(email: tEmail, password: tPassword), ); // assert expect(result.isLeft(), true); result.fold( (failure) { expect(failure, isA()); expect(failure.message, contains('네트워크')); }, (_) => fail('Should return failure'), ); }); test('서버 에러 시 ServerFailure 반환', () async { // arrange final dioError = DioException( requestOptions: RequestOptions(path: '/login'), response: Response( requestOptions: RequestOptions(path: '/login'), statusCode: 500, data: {'message': '서버 내부 오류'}, ), type: DioExceptionType.badResponse, ); when(mockAuthService.login(any)).thenThrow(dioError); // act final result = await loginUseCase( LoginParams(email: tEmail, password: tPassword), ); // assert expect(result.isLeft(), true); result.fold( (failure) { expect(failure, isA()); expect(failure.message, contains('서버')); }, (_) => fail('Should return failure'), ); }); test('예상치 못한 에러 시 UnknownFailure 반환', () async { // arrange when(mockAuthService.login(any)) .thenThrow(Exception('Unexpected error')); // act final result = await loginUseCase( LoginParams(email: tEmail, password: tPassword), ); // assert expect(result.isLeft(), true); result.fold( (failure) { expect(failure, isA()); expect(failure.message, contains('오류')); }, (_) => fail('Should return failure'), ); }); test('로그인 실패 시 (null 반환) AuthFailure 반환', () async { // arrange when(mockAuthService.login(any)).thenAnswer((_) async => null); // act final result = await loginUseCase( LoginParams(email: tEmail, password: tPassword), ); // assert expect(result.isLeft(), true); result.fold( (failure) { expect(failure, isA()); expect(failure.message, contains('로그인')); }, (_) => fail('Should return failure'), ); }); }); }