import 'dart:convert'; import 'dart:io'; import 'package:swagger_generator_flutter/core/error_reporter.dart'; import 'package:swagger_generator_flutter/core/performance_parser.dart'; import 'package:swagger_generator_flutter/generators/retrofit_api_generator.dart'; import 'package:swagger_generator_flutter/validators/enhanced_validator.dart'; import 'package:test/test.dart'; void main() { group('Integration Tests', () { group('End-to-End Workflow', () { test('complete workflow from JSON to generated code', () async { // 1. 准备测试数据 final testApiJson = { 'openapi': '3.0.3', 'info': { 'title': 'Integration Test API', 'version': '1.0.0', 'description': 'API for integration testing', }, 'servers': [ { 'url': 'https://api.example.com', 'description': 'Production server', }, ], 'paths': { '/users': { 'get': { 'summary': 'Get users', 'operationId': 'getUsers', 'tags': ['users'], 'parameters': [ { 'name': 'page', 'in': 'query', 'required': false, 'schema': {'type': 'integer', 'default': 1}, 'description': 'Page number', }, { 'name': 'limit', 'in': 'query', 'required': false, 'schema': {'type': 'integer', 'default': 20}, 'description': 'Items per page', }, ], 'responses': { '200': { 'description': 'Success', 'content': { 'application/json': { 'schema': { 'type': 'object', 'properties': { 'data': { 'type': 'array', 'items': { r'$ref': '#/components/schemas/User', }, }, 'total': {'type': 'integer'}, 'page': {'type': 'integer'}, 'limit': {'type': 'integer'}, }, }, }, }, }, '400': { 'description': 'Bad request', }, }, }, 'post': { 'summary': 'Create user', 'operationId': 'createUser', 'tags': ['users'], 'requestBody': { 'required': true, 'content': { 'application/json': { 'schema': { r'$ref': '#/components/schemas/CreateUserRequest', }, }, }, }, 'responses': { '201': { 'description': 'User created', 'content': { 'application/json': { 'schema': { r'$ref': '#/components/schemas/User', }, }, }, }, '400': { 'description': 'Invalid input', }, }, }, }, '/users/{id}': { 'get': { 'summary': 'Get user by ID', 'operationId': 'getUserById', 'tags': ['users'], 'parameters': [ { 'name': 'id', 'in': 'path', 'required': true, 'schema': {'type': 'integer'}, 'description': 'User ID', }, ], 'responses': { '200': { 'description': 'User found', 'content': { 'application/json': { 'schema': { r'$ref': '#/components/schemas/User', }, }, }, }, '404': { 'description': 'User not found', }, }, }, }, '/files/upload': { 'post': { 'summary': 'Upload file', 'operationId': 'uploadFile', 'tags': ['files'], 'requestBody': { 'required': true, 'content': { 'multipart/form-data': { 'schema': { 'type': 'object', 'properties': { 'file': { 'type': 'string', 'format': 'binary', }, 'description': { 'type': 'string', }, }, 'required': ['file'], }, }, }, }, 'responses': { '200': { 'description': 'File uploaded', 'content': { 'application/json': { 'schema': { r'$ref': '#/components/schemas/FileUploadResult', }, }, }, }, }, }, }, }, 'components': { 'schemas': { 'User': { 'type': 'object', 'properties': { 'id': { 'type': 'integer', 'format': 'int64', }, 'name': { 'type': 'string', 'maxLength': 100, }, 'email': { 'type': 'string', 'format': 'email', }, 'createdAt': { 'type': 'string', 'format': 'date-time', }, }, 'required': ['id', 'name', 'email'], }, 'CreateUserRequest': { 'type': 'object', 'properties': { 'name': { 'type': 'string', 'maxLength': 100, }, 'email': { 'type': 'string', 'format': 'email', }, }, 'required': ['name', 'email'], }, 'FileUploadResult': { 'type': 'object', 'properties': { 'url': { 'type': 'string', 'format': 'uri', }, 'filename': { 'type': 'string', }, 'size': { 'type': 'integer', }, 'contentType': { 'type': 'string', }, }, 'required': ['url', 'filename', 'size'], }, }, 'securitySchemes': { 'bearerAuth': { 'type': 'http', 'scheme': 'bearer', 'bearerFormat': 'JWT', }, }, }, 'security': [ { 'bearerAuth': [], }, ], }; final jsonString = jsonEncode(testApiJson); // 2. 解析 JSON 为 SwaggerDocument final parser = PerformanceParser( config: const ParseConfig( enablePerformanceStats: true, enableParallelParsing: false, // 禁用并行解析避免类型转换问题 ), ); final document = await parser.parseDocument(jsonString); // 验证解析结果 expect(document.title, equals('Integration Test API')); expect(document.version, equals('1.0.0')); expect(document.paths.length, greaterThanOrEqualTo(3)); expect(document.models.length, equals(3)); expect(document.servers.length, equals(1)); // 检查解析性能 final parseStats = parser.lastStats; expect(parseStats, isNotNull); expect(parseStats!.totalTime.inMilliseconds, lessThan(5000)); // 3. 验证文档 final validator = EnhancedValidator(); final isValid = validator.validateDocument(document); expect(isValid, isTrue); final errors = validator.errorReporter.errors; final criticalErrors = errors .where( (e) => e.severity == ErrorSeverity.error || e.severity == ErrorSeverity.critical, ) .toList(); expect( criticalErrors, isEmpty, reason: 'Document should not have critical errors: ${criticalErrors.map((e) => e.title).join(", ")}', ); // 4. 生成 Retrofit API 代码 final retrofitGenerator = RetrofitApiGenerator( className: 'IntegrationTestApi', splitByTags: false, // 不拆分,生成单个文件以便测试 ); final retrofitCode = retrofitGenerator.generateFromDocument(document); // 验证生成的代码 expect(retrofitCode, isNotEmpty); expect(retrofitCode, contains('IntegrationTestApi')); expect(retrofitCode, contains("@GET('/users')")); expect(retrofitCode, contains("@POST('/users')")); expect(retrofitCode, contains("@GET('/users/{id}')")); expect(retrofitCode, contains("@POST('/files/upload')")); expect(retrofitCode, contains("@Path('id')")); expect(retrofitCode, contains("@Query('page')")); expect(retrofitCode, contains('@MultiPart()')); // 5. 性能验证 print('Integration Test Performance Summary:'); print(' Parse Time: ${parseStats.totalTime.inMilliseconds}ms'); print( ' Document Size: ${(jsonString.length / 1024).toStringAsFixed(2)}KB', ); print(' Paths Parsed: ${parseStats.pathCount}'); print(' Schemas Parsed: ${parseStats.schemaCount}'); print( ' Retrofit Code Size: ${(retrofitCode.length / 1024).toStringAsFixed(2)}KB', ); // 验证性能指标 expect( parseStats.totalTime.inMilliseconds, lessThan(2000), ); // 解析应在2秒内完成 expect(retrofitCode.length, greaterThan(1000)); // 应生成足够的代码 }); test('handles real project swagger.json', () async { final file = File('swagger.json'); if (!file.existsSync()) { print( 'swagger.json not found, skipping real project integration test', ); return; } final jsonString = await file.readAsString(); print( 'Real project swagger.json size: ${(jsonString.length / 1024).toStringAsFixed(2)}KB', ); // 解析 final parser = PerformanceParser( config: const ParseConfig( enablePerformanceStats: true, enableParallelParsing: false, // 禁用并行解析 ), ); final parseStopwatch = Stopwatch()..start(); final document = await parser.parseDocument(jsonString); parseStopwatch.stop(); expect(document, isNotNull); expect(document.paths.isNotEmpty, isTrue); print('Real project parsing results:'); print(' Parse Time: ${parseStopwatch.elapsedMilliseconds}ms'); print(' Paths: ${document.paths.length}'); print(' Models: ${document.models.length}'); print(' Servers: ${document.servers.length}'); // 验证 final validator = EnhancedValidator(includeWarnings: false); final isValid = validator.validateDocument(document); final errors = validator.errorReporter.getErrorsBySeverity(ErrorSeverity.error); final criticalErrors = validator.errorReporter.getErrorsBySeverity(ErrorSeverity.critical); print('Validation results:'); print(' Valid: $isValid'); print(' Errors: ${errors.length}'); print(' Critical: ${criticalErrors.length}'); // 生成代码(使用 RetrofitApiGenerator) final generator = RetrofitApiGenerator( className: 'OAMobileApiService', ); final genStopwatch = Stopwatch()..start(); final generatedCode = generator.generateFromDocument(document); genStopwatch.stop(); expect(generatedCode, isNotEmpty); expect(generatedCode, contains('OAMobileApiService')); print('Code generation results:'); print(' Generation Time: ${genStopwatch.elapsedMilliseconds}ms'); print( ' Generated Code Size: ${(generatedCode.length / 1024).toStringAsFixed(2)}KB', ); print(' Generated Lines: ${generatedCode.split('\n').length}'); // 性能要求 expect(parseStopwatch.elapsedMilliseconds, lessThan(15000)); // 15秒内解析完成 expect(genStopwatch.elapsedMilliseconds, lessThan(10000)); // 10秒内生成完成 expect(generatedCode.length, greaterThan(1000)); // 至少生成1KB代码 }); }); group('Error Handling Integration', () { test('handles malformed JSON gracefully', () async { const malformedJson = '{"openapi": "3.0.3", "info": {"title": "Test"'; // 缺少闭合括号 final parser = PerformanceParser(); expect( () => parser.parseDocument(malformedJson), throwsA(isA()), ); }); test('handles invalid OpenAPI document', () async { final invalidDoc = { 'openapi': '3.0.3', 'info': { 'title': 'Invalid API', // 缺少 version }, 'paths': {}, // 空路径 }; final jsonString = jsonEncode(invalidDoc); final parser = PerformanceParser(); expect( () => parser.parseDocument(jsonString), throwsA(isA()), ); }); test('validation catches common errors', () async { final problematicDoc = { 'openapi': '3.0.3', 'info': { 'title': 'Problematic API', 'version': '1.0.0', }, 'paths': { '/users/{id}': { 'get': { 'summary': 'Get user', 'responses': { '200': { 'description': 'Success', }, }, // 缺少路径参数声明 }, }, }, }; final jsonString = jsonEncode(problematicDoc); final parser = PerformanceParser(); final document = await parser.parseDocument(jsonString); final validator = EnhancedValidator()..validateDocument(document); // The validator should run without throwing // Validation results may vary based on implementation expect(validator.errorReporter.errors, isNotNull); }); }); group('Performance Integration', () { test('handles large documents efficiently', () async { // 创建大型文档 final paths = {}; final schemas = {}; for (var i = 0; i < 200; i++) { paths['/resource$i'] = { 'get': { 'summary': 'Get resource $i', 'operationId': 'getResource$i', 'tags': ['resources'], 'responses': { '200': { 'description': 'Success', 'content': { 'application/json': { 'schema': { r'$ref': '#/components/schemas/Resource$i', }, }, }, }, }, }, }; schemas['Resource$i'] = { 'type': 'object', 'properties': { 'id': {'type': 'integer'}, 'name': {'type': 'string'}, 'value$i': {'type': 'string'}, }, 'required': ['id', 'name'], }; } final largeDoc = { 'openapi': '3.0.3', 'info': { 'title': 'Large API', 'version': '1.0.0', }, 'paths': paths, 'components': { 'schemas': schemas, }, }; final jsonString = jsonEncode(largeDoc); print( 'Large document size: ${(jsonString.length / 1024).toStringAsFixed(2)}KB', ); // 测试解析性能 final parser = PerformanceParser( config: const ParseConfig( enablePerformanceStats: true, enableParallelParsing: false, // 禁用并行解析 ), ); final parseStopwatch = Stopwatch()..start(); final document = await parser.parseDocument(jsonString); parseStopwatch.stop(); expect(document.paths.length, greaterThan(100)); expect(document.models.length, greaterThan(100)); expect(parseStopwatch.elapsedMilliseconds, lessThan(10000)); // 10秒内完成 // 测试生成性能(使用 RetrofitApiGenerator) final generator = RetrofitApiGenerator(splitByTags: false); final genStopwatch = Stopwatch()..start(); final generatedCode = generator.generateFromDocument(document); genStopwatch.stop(); expect(generatedCode.length, greaterThan(1000)); // 至少1KB代码 expect(genStopwatch.elapsedMilliseconds, lessThan(15000)); // 15秒内完成 print('Large document performance:'); print(' Parse Time: ${parseStopwatch.elapsedMilliseconds}ms'); print(' Generation Time: ${genStopwatch.elapsedMilliseconds}ms'); print(' Paths: ${document.paths.length}'); print(' Models: ${document.models.length}'); print( ' Generated Code: ${(generatedCode.length / 1024).toStringAsFixed(2)}KB', ); }); }); }); } // 忽略测试构造数据的类型推断与打印告警,便于保持示例简洁 // ignore_for_file: inference_failure_on_collection_literal, avoid_print