feat: add AI recommendations flow for tenders
Implement company AI onboarding/recommendation models, services, repository, and tender UI integration with supporting tests. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:tm_app/data/services/model/onboarding_response/onboarding_response.dart';
|
||||
|
||||
void main() {
|
||||
group('OnboardingResponse Model Test', () {
|
||||
final mockJson = {
|
||||
'success': true,
|
||||
'message': 'AI onboarding started successfully',
|
||||
'data': {'status': 'started'},
|
||||
'error': {'message': null, 'code': null, 'details': null},
|
||||
};
|
||||
|
||||
test('fromJson creates valid OnboardingResponse instance', () {
|
||||
final response = OnboardingResponse.fromJson(mockJson);
|
||||
|
||||
expect(response.success, true);
|
||||
expect(response.message, 'AI onboarding started successfully');
|
||||
expect(response.data?.status, 'started');
|
||||
});
|
||||
|
||||
test('handles null data gracefully', () {
|
||||
final response = OnboardingResponse.fromJson({
|
||||
'success': false,
|
||||
'message': 'AI service not configured',
|
||||
'data': null,
|
||||
'error': {'message': 'unavailable', 'code': '503', 'details': null},
|
||||
});
|
||||
|
||||
expect(response.success, false);
|
||||
expect(response.data, isNull);
|
||||
expect(response.error?.message, 'unavailable');
|
||||
});
|
||||
|
||||
test('toJson round-trips status', () {
|
||||
final response = OnboardingResponse.fromJson(mockJson);
|
||||
final json = response.toJson();
|
||||
final data = Map<String, dynamic>.from(json['data'] as Map);
|
||||
|
||||
expect(json['success'], true);
|
||||
expect(data['status'], 'started');
|
||||
});
|
||||
|
||||
test('equality and copyWith work as expected', () {
|
||||
final response = OnboardingResponse.fromJson(mockJson);
|
||||
final updated = response.copyWith(message: 'Updated');
|
||||
|
||||
expect(updated.message, 'Updated');
|
||||
expect(updated != response, true);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:tm_app/data/services/model/recommend_response/recommend_response.dart';
|
||||
|
||||
void main() {
|
||||
group('RecommendResponse Model Test', () {
|
||||
final mockJson = {
|
||||
'success': true,
|
||||
'message': 'AI recommendations retrieved successfully',
|
||||
'data': [
|
||||
{
|
||||
'rank': '1',
|
||||
'tender_id': '674a1b2c3d4e5f6789012345',
|
||||
'analysis': 'Strong match based on company industry and CPV codes.',
|
||||
},
|
||||
{
|
||||
'rank': '2',
|
||||
'tender_id': '674a1b2c3d4e5f6789012346',
|
||||
'analysis': 'Relevant scope and geographic fit.',
|
||||
},
|
||||
],
|
||||
'error': {'message': null, 'code': null, 'details': null},
|
||||
};
|
||||
|
||||
test('fromJson parses the ranked recommendation list', () {
|
||||
final response = RecommendResponse.fromJson(mockJson);
|
||||
|
||||
expect(response.success, true);
|
||||
expect(response.data, isNotNull);
|
||||
expect(response.data!.length, 2);
|
||||
expect(response.data!.first.rank, '1');
|
||||
expect(response.data!.first.tenderId, '674a1b2c3d4e5f6789012345');
|
||||
expect(
|
||||
response.data!.first.analysis,
|
||||
'Strong match based on company industry and CPV codes.',
|
||||
);
|
||||
});
|
||||
|
||||
test('handles empty data (AI still indexing)', () {
|
||||
final response = RecommendResponse.fromJson({
|
||||
'success': true,
|
||||
'message': 'AI recommendations retrieved successfully',
|
||||
'data': <dynamic>[],
|
||||
'error': null,
|
||||
});
|
||||
|
||||
expect(response.success, true);
|
||||
expect(response.data, isEmpty);
|
||||
});
|
||||
|
||||
test('toJson round-trips the nested items', () {
|
||||
final response = RecommendResponse.fromJson(mockJson);
|
||||
final json = response.toJson();
|
||||
final data = (json['data'] as List).cast<Map<String, dynamic>>();
|
||||
|
||||
expect(json['success'], true);
|
||||
expect(data.length, 2);
|
||||
expect(data[1]['tender_id'], '674a1b2c3d4e5f6789012346');
|
||||
expect(data[1]['rank'], '2');
|
||||
});
|
||||
|
||||
test('equality and copyWith work as expected', () {
|
||||
final response = RecommendResponse.fromJson(mockJson);
|
||||
final updated = response.copyWith(message: 'Updated');
|
||||
|
||||
expect(updated.message, 'Updated');
|
||||
expect(updated != response, true);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user