fix : update local.properties path and improve null safety in chicken_local_imp.dart and chicken_repository_imp.dart; refactor profile view for better readability

This commit is contained in:
2025-10-19 09:47:33 +03:30
parent 464dacc39b
commit 6e4e3159d1
17 changed files with 3183 additions and 362 deletions

View File

@@ -0,0 +1,350 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:rasadyar_chicken/data/data_source/remote/auth/auth_remote_imp.dart';
import 'package:rasadyar_chicken/data/models/response/user_info/user_info_model.dart';
import 'package:rasadyar_chicken/data/models/response/user_profile_model/user_profile_model.dart';
import 'package:rasadyar_core/core.dart';
import 'package:dio/dio.dart';
class MockDioRemote extends Mock implements DioRemote {}
void main() {
late AuthRemoteDataSourceImp authRemoteDataSource;
late MockDioRemote mockDioRemote;
setUpAll(() {
registerFallbackValue(<String, dynamic>{});
registerFallbackValue(<String, String>{});
});
setUp(() {
mockDioRemote = MockDioRemote();
authRemoteDataSource = AuthRemoteDataSourceImp(mockDioRemote);
});
group('AuthRemoteDataSourceImp', () {
group('login', () {
test('should return UserProfileModel when login is successful', () async {
// Arrange
final authRequest = {
'username': 'test@example.com',
'password': 'password',
};
final expectedUserProfile = UserProfileModel(
accessToken: 'test-access-token',
expiresIn: '3600',
scope: 'read write',
expireTime: '2024-12-31T23:59:59Z',
mobile: '09123456789',
fullname: 'John Doe',
firstname: 'John',
lastname: 'Doe',
city: 'Tehran',
province: 'Tehran',
nationalCode: '1234567890',
nationalId: '1234567890',
);
final mockResponse = DioResponse<UserProfileModel?>(
Response(
data: expectedUserProfile,
statusCode: 200,
requestOptions: RequestOptions(path: '/api/login/'),
),
);
when(
() => mockDioRemote.post<UserProfileModel?>(
'/api/login/',
data: authRequest,
fromJson: any(named: 'fromJson'),
headers: any(named: 'headers'),
),
).thenAnswer((_) async => mockResponse);
// Act
final result = await authRemoteDataSource.login(
authRequest: authRequest,
);
// Assert
expect(result, equals(expectedUserProfile));
verify(
() => mockDioRemote.post<UserProfileModel?>(
'/api/login/',
data: authRequest,
fromJson: UserProfileModel.fromJson,
headers: {'Content-Type': 'application/json'},
),
).called(1);
});
test('should return null when login fails', () async {
// Arrange
final authRequest = {
'username': 'test@example.com',
'password': 'wrong',
};
final mockResponse = DioResponse<UserProfileModel?>(
Response(
data: null,
statusCode: 401,
requestOptions: RequestOptions(path: '/api/login/'),
),
);
when(
() => mockDioRemote.post<UserProfileModel?>(
'/api/login/',
data: authRequest,
fromJson: any(named: 'fromJson'),
headers: any(named: 'headers'),
),
).thenAnswer((_) async => mockResponse);
// Act
final result = await authRemoteDataSource.login(
authRequest: authRequest,
);
// Assert
expect(result, isNull);
verify(
() => mockDioRemote.post<UserProfileModel?>(
'/api/login/',
data: authRequest,
fromJson: UserProfileModel.fromJson,
headers: {'Content-Type': 'application/json'},
),
).called(1);
});
});
group('hasAuthenticated', () {
test('should return true when user is authenticated', () async {
// Arrange
final mockResponse = DioResponse<bool>(
Response(
data: true,
statusCode: 200,
requestOptions: RequestOptions(path: 'auth/api/v1/login/'),
),
);
when(
() => mockDioRemote.get<bool>(
'auth/api/v1/login/',
headers: {'Content-Type': 'application/json'},
),
).thenAnswer((_) async => mockResponse);
// Act
final result = await authRemoteDataSource.hasAuthenticated();
// Assert
expect(result, isTrue);
verify(
() => mockDioRemote.get<bool>(
'auth/api/v1/login/',
headers: {'Content-Type': 'application/json'},
),
).called(1);
});
test('should return false when user is not authenticated', () async {
// Arrange
final mockResponse = DioResponse<bool>(
Response(
data: false,
statusCode: 401,
requestOptions: RequestOptions(path: 'auth/api/v1/login/'),
),
);
when(
() => mockDioRemote.get<bool>(
'auth/api/v1/login/',
headers: {'Content-Type': 'application/json'},
),
).thenAnswer((_) async => mockResponse);
// Act
final result = await authRemoteDataSource.hasAuthenticated();
// Assert
expect(result, isFalse);
verify(
() => mockDioRemote.get<bool>(
'auth/api/v1/login/',
headers: {'Content-Type': 'application/json'},
),
).called(1);
});
test('should return false when response data is null', () async {
// Arrange
final mockResponse = DioResponse<bool>(
Response(
data: null,
statusCode: 200,
requestOptions: RequestOptions(path: 'auth/api/v1/login/'),
),
);
when(
() => mockDioRemote.get<bool>(
'auth/api/v1/login/',
headers: {'Content-Type': 'application/json'},
),
).thenAnswer((_) async => mockResponse);
// Act
final result = await authRemoteDataSource.hasAuthenticated();
// Assert
expect(result, isFalse);
verify(
() => mockDioRemote.get<bool>(
'auth/api/v1/login/',
headers: {'Content-Type': 'application/json'},
),
).called(1);
});
});
group('getUserInfo', () {
test('should return UserInfoModel when user info is found', () async {
// Arrange
const phoneNumber = '09123456789';
final expectedUserInfo = UserInfoModel(
isUser: true,
address: 'Test Address',
backend: 'test-backend',
apiKey: 'test-api-key',
);
final mockResponse = DioResponse<UserInfoModel?>(
Response(
data: expectedUserInfo,
statusCode: 200,
requestOptions: RequestOptions(
path: 'https://userbackend.rasadyaar.ir/api/send_otp/',
),
),
);
when(
() => mockDioRemote.post<UserInfoModel?>(
'https://userbackend.rasadyaar.ir/api/send_otp/',
data: {"mobile": phoneNumber, "state": ""},
fromJson: any(named: 'fromJson'),
headers: any(named: 'headers'),
),
).thenAnswer((_) async => mockResponse);
// Act
final result = await authRemoteDataSource.getUserInfo(phoneNumber);
// Assert
expect(result, equals(expectedUserInfo));
verify(
() => mockDioRemote.post<UserInfoModel?>(
'https://userbackend.rasadyaar.ir/api/send_otp/',
data: {"mobile": phoneNumber, "state": ""},
fromJson: UserInfoModel.fromJson,
headers: {'Content-Type': 'application/json'},
),
).called(1);
});
test('should return null when user info is not found', () async {
// Arrange
const phoneNumber = '09123456789';
final mockResponse = DioResponse<UserInfoModel?>(
Response(
data: null,
statusCode: 404,
requestOptions: RequestOptions(
path: 'https://userbackend.rasadyaar.ir/api/send_otp/',
),
),
);
when(
() => mockDioRemote.post<UserInfoModel?>(
'https://userbackend.rasadyaar.ir/api/send_otp/',
data: {"mobile": phoneNumber, "state": ""},
fromJson: any(named: 'fromJson'),
headers: any(named: 'headers'),
),
).thenAnswer((_) async => mockResponse);
// Act
final result = await authRemoteDataSource.getUserInfo(phoneNumber);
// Assert
expect(result, isNull);
verify(
() => mockDioRemote.post<UserInfoModel?>(
'https://userbackend.rasadyaar.ir/api/send_otp/',
data: {"mobile": phoneNumber, "state": ""},
fromJson: UserInfoModel.fromJson,
headers: {'Content-Type': 'application/json'},
),
).called(1);
});
});
group('submitUserInfo', () {
test(
'should call remote submitUserInfo with correct parameters',
() async {
// Arrange
final userInfo = {
'mobile': '09123456789',
'device_name': 'Test Device',
};
final mockResponse = DioResponse<dynamic>(
Response(
data: null,
statusCode: 200,
requestOptions: RequestOptions(path: '/steward-app-login/'),
),
);
when(
() => mockDioRemote.post(
'/steward-app-login/',
data: userInfo,
headers: any(named: 'headers'),
),
).thenAnswer((_) async => mockResponse);
// Act
await authRemoteDataSource.submitUserInfo(userInfo);
// Assert
verify(
() => mockDioRemote.post(
'/steward-app-login/',
data: userInfo,
headers: {'Content-Type': 'application/json'},
),
).called(1);
},
);
});
group('logout', () {
test('should throw UnimplementedError', () async {
// Act & Assert
expect(
() => authRemoteDataSource.logout(),
throwsA(isA<UnimplementedError>()),
);
});
});
});
}