From 5979dbc5992cf2287a7ba5a3a6ae09bfbe78e020 Mon Sep 17 00:00:00 2001 From: Nialixus Date: Sun, 2 Jun 2024 12:56:33 +0700 Subject: [PATCH] Finish create test template --- bin/api_bloc.dart | 8 + .../controllers/read_controller_test.dart | 74 ++++++++ bin/src/read/models/read_model_test.dart | 45 +++++ bin/src/read/read.dart | 5 + bin/src/read/views/read_view.dart | 4 +- bin/src/read/views/read_view_test.dart | 124 ++++++++++++ bin/src/shared/models/shared_enum.dart | 8 - bin/src/shared/shared.dart | 27 ++- bin/src/shared/shared_enum.dart | 20 ++ .../shared/{models => }/shared_extension.dart | 2 +- .../shared/{models => }/shared_runner.dart | 6 +- .../controllers/write_controller_test.dart | 90 +++++++++ bin/src/write/models/write_model_test.dart | 50 +++++ bin/src/write/views/write_view.dart | 4 +- bin/src/write/views/write_view_test.dart | 177 ++++++++++++++++++ bin/src/write/write.dart | 5 + example/lib/main.dart | 3 +- example/lib/src/get/get.dart | 2 +- .../views/{get_page.dart => get_view.dart} | 4 +- example/lib/src/post/post.dart | 2 +- .../views/{post_page.dart => post_view.dart} | 4 +- .../lib/src_generated_template/auth/auth.dart | 13 -- .../auth/controllers/auth_data.dart | 12 -- .../auth/controllers/auth_update.dart | 18 -- .../auth/models/auth_data.dart | 5 - .../auth/models/auth_update.dart | 10 - .../auth/views/auth_data.dart | 19 -- .../auth/views/auth_update.dart | 23 --- .../user/controllers/user_data.dart | 12 -- .../user/controllers/user_update.dart | 18 -- .../user/models/user_data.dart | 5 - .../user/models/user_update.dart | 9 - .../lib/src_generated_template/user/user.dart | 14 -- .../user/views/user_data.dart | 19 -- .../user/views/user_update.dart | 23 --- .../src/get/controllers/get_controller.dart | 55 ++++++ example/test/src/get/models/get_model.dart | 15 ++ example/test/src/get/views/get_view.dart | 143 ++++++++++++++ 38 files changed, 849 insertions(+), 228 deletions(-) create mode 100644 bin/src/read/controllers/read_controller_test.dart create mode 100644 bin/src/read/models/read_model_test.dart create mode 100644 bin/src/read/views/read_view_test.dart delete mode 100644 bin/src/shared/models/shared_enum.dart create mode 100644 bin/src/shared/shared_enum.dart rename bin/src/shared/{models => }/shared_extension.dart (93%) rename bin/src/shared/{models => }/shared_runner.dart (92%) create mode 100644 bin/src/write/controllers/write_controller_test.dart create mode 100644 bin/src/write/models/write_model_test.dart create mode 100644 bin/src/write/views/write_view_test.dart rename example/lib/src/get/views/{get_page.dart => get_view.dart} (94%) rename example/lib/src/post/views/{post_page.dart => post_view.dart} (97%) delete mode 100644 example/lib/src_generated_template/auth/auth.dart delete mode 100644 example/lib/src_generated_template/auth/controllers/auth_data.dart delete mode 100644 example/lib/src_generated_template/auth/controllers/auth_update.dart delete mode 100644 example/lib/src_generated_template/auth/models/auth_data.dart delete mode 100644 example/lib/src_generated_template/auth/models/auth_update.dart delete mode 100644 example/lib/src_generated_template/auth/views/auth_data.dart delete mode 100644 example/lib/src_generated_template/auth/views/auth_update.dart delete mode 100644 example/lib/src_generated_template/user/controllers/user_data.dart delete mode 100644 example/lib/src_generated_template/user/controllers/user_update.dart delete mode 100644 example/lib/src_generated_template/user/models/user_data.dart delete mode 100644 example/lib/src_generated_template/user/models/user_update.dart delete mode 100644 example/lib/src_generated_template/user/user.dart delete mode 100644 example/lib/src_generated_template/user/views/user_data.dart delete mode 100644 example/lib/src_generated_template/user/views/user_update.dart create mode 100644 example/test/src/get/controllers/get_controller.dart create mode 100644 example/test/src/get/models/get_model.dart create mode 100644 example/test/src/get/views/get_view.dart diff --git a/bin/api_bloc.dart b/bin/api_bloc.dart index 384c222..f9b6af5 100644 --- a/bin/api_bloc.dart +++ b/bin/api_bloc.dart @@ -39,6 +39,14 @@ Future main(List arguments) async { ReadView(argument), WriteView(argument), ], + testRunner: [ + ReadControllerTest(argument), + WriteControllerTest(argument), + ReadModelTest(argument), + WriteModelTest(argument), + ReadViewTest(argument), + WriteViewTest(argument), + ], ).run(buffer); print(buffer); diff --git a/bin/src/read/controllers/read_controller_test.dart b/bin/src/read/controllers/read_controller_test.dart new file mode 100644 index 0000000..446b14a --- /dev/null +++ b/bin/src/read/controllers/read_controller_test.dart @@ -0,0 +1,74 @@ +part of '../read.dart'; + +class ReadControllerTest extends SharedRunner { + ReadControllerTest( + super.data, { + super.type = SharedType.controllers, + }); + + @override + Directory get directory { + return Directory( + '${data['output']}' + .toLowerCase() + .toPath + .replaceFirst(RegExp(r'(^|/)\blib/'), 'test/') + + module.toLowerCase().toPath, + )..createSync(recursive: true); + } + + @override + List get submodules { + return data['read']; + } + + @override + String template({ + required String module, + required String submodule, + }) { + return ''' +// ignore: avoid_relative_lib_imports +import '../../../../${directory.path.replaceFirst(RegExp(r'(^|/)\btest/'), 'lib/')}/${module.toLowerCase()}.dart'; +import 'package:api_bloc/api_bloc.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('${module.toCamelCase()}${submodule.toCamelCase()}Controller', () { + late ${module.toCamelCase()}${submodule.toCamelCase()}Controller controller; + + setUp(() { + controller = ${module.toCamelCase()}${submodule.toCamelCase()}Controller(); + }); + + tearDown(() { + controller.dispose(); + }); + + test('Validate Loading State', () async { + await controller.run(); + expect(controller.value, isA()); + expect(controller.value.data, isNull); + expect(controller.value.message, equals('Fetching On Progress')); + }); + + test('Validate Success State', () async { + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isA<${module.toCamelCase()}${submodule.toCamelCase()}Model>()); + expect(controller.value.message, equals('Data Successfully Fetched')); + }); + + test('Validate Error State', () async { + await controller.run(); + expect(controller.value, isA()); + expect(controller.value.message, equals('Something Went Wrong')); + expect(controller.value.data, isNotNull); + expect(controller.value.data, isA()); + }); + }); +} +'''; + } +} diff --git a/bin/src/read/models/read_model_test.dart b/bin/src/read/models/read_model_test.dart new file mode 100644 index 0000000..d28b943 --- /dev/null +++ b/bin/src/read/models/read_model_test.dart @@ -0,0 +1,45 @@ +part of '../read.dart'; + +class ReadModelTest extends SharedRunner { + ReadModelTest( + super.data, { + super.type = SharedType.models, + }); + + @override + Directory get directory { + return Directory( + '${data['output']}' + .toLowerCase() + .toPath + .replaceFirst(RegExp(r'(^|/)\blib/'), 'test/') + + module.toLowerCase().toPath, + )..createSync(recursive: true); + } + + @override + List get submodules { + return data['read']; + } + + @override + String template({ + required String module, + required String submodule, + }) { + return ''' +// ignore: avoid_relative_lib_imports +import '../../../../${directory.path.replaceFirst(RegExp(r'(^|/)\btest/'), 'lib/')}/${module.toLowerCase()}.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('${module.toCamelCase()}${submodule.toCamelCase()}Model', () { + test('Validate Type', () { + const ${module.toCamelCase()}${submodule.toCamelCase()}Model data = ${module.toCamelCase()}${submodule.toCamelCase()}Model.test(); + expect(data, isA<${module.toCamelCase()}${submodule.toCamelCase()}Model>()); + }); + }); +} +'''; + } +} diff --git a/bin/src/read/read.dart b/bin/src/read/read.dart index c84cc61..42ac0e6 100644 --- a/bin/src/read/read.dart +++ b/bin/src/read/read.dart @@ -1,7 +1,12 @@ library read; +import 'dart:io'; + import '../shared/shared.dart'; +part 'controllers/read_controller_test.dart'; part 'controllers/read_controller.dart'; +part 'models/read_model_test.dart'; part 'models/read_model.dart'; +part 'views/read_view_test.dart'; part 'views/read_view.dart'; diff --git a/bin/src/read/views/read_view.dart b/bin/src/read/views/read_view.dart index 3fe253a..c56eee7 100644 --- a/bin/src/read/views/read_view.dart +++ b/bin/src/read/views/read_view.dart @@ -19,8 +19,8 @@ final class ReadView extends SharedRunner { return ''' part of '../$module.dart'; -class ${module.toCamelCase()}${submodule.toCamelCase()}${type.name.toCamelCase()} extends StatelessWidget { - const ${module.toCamelCase()}${submodule.toCamelCase()}${type.name.toCamelCase()}({super.key}); +class ${module.toCamelCase()}${submodule.toCamelCase()}${type.toString().toCamelCase()} extends StatelessWidget { + const ${module.toCamelCase()}${submodule.toCamelCase()}${type.toString().toCamelCase()}({super.key}); @override Widget build(BuildContext context) { diff --git a/bin/src/read/views/read_view_test.dart b/bin/src/read/views/read_view_test.dart new file mode 100644 index 0000000..ef46bd3 --- /dev/null +++ b/bin/src/read/views/read_view_test.dart @@ -0,0 +1,124 @@ +part of '../read.dart'; + +class ReadViewTest extends SharedRunner { + ReadViewTest( + super.data, { + super.type = SharedType.views, + }); + + @override + Directory get directory { + return Directory( + '${data['output']}' + .toLowerCase() + .toPath + .replaceFirst(RegExp(r'(^|/)\blib/'), 'test/') + + module.toLowerCase().toPath, + )..createSync(recursive: true); + } + + @override + List get submodules { + return data['read']; + } + + @override + String template({ + required String module, + required String submodule, + }) { + return ''' +// ignore: avoid_relative_lib_imports +import '../../../../${directory.path.replaceFirst(RegExp(r'(^|/)\btest/'), 'lib/')}/${module.toLowerCase()}.dart'; +import 'package:api_bloc/api_bloc.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('${module.toCamelCase()}${submodule.toCamelCase()}View', () { + + testWidgets('Validate Loading Consumer', (tester) async { + late ${module.toCamelCase()}${submodule.toCamelCase()}Controller controller; + + setUp(() { + controller = ${module.toCamelCase()}${submodule.toCamelCase()}Controller(); + }); + + tearDown(() { + controller.dispose(); + }); + + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isNull); + expect(controller.value.message, equals('Submitting In Progress')); + + expect(() async { + await tester.pumpWidget(const MaterialApp(home: ${module.toCamelCase()}${submodule.toCamelCase()}View())); + await tester.pump(); + expect(find.byType(Text), findsNothing); + expect(find.text('Submitting In Progress'), findsNothing); + expect(find.byType(CircularProgressIndicator), findsOneWidget); + expect(find.byType(SnackBar), findsNothing); + }, returnsNormally); + }); + + testWidgets('Validate Success Consumer', (tester) async { + late ${module.toCamelCase()}${submodule.toCamelCase()}Controller controller; + + setUp(() { + controller = ${module.toCamelCase()}${submodule.toCamelCase()}Controller(); + }); + + tearDown(() { + controller.dispose(); + }); + + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isA<${module.toCamelCase()}${submodule.toCamelCase()}Model>()); + expect(controller.value.message, equals('Data Successfully Submitted')); + + expect(() async { + await tester.pumpWidget(const MaterialApp(home: ${module.toCamelCase()}${submodule.toCamelCase()}View())); + await tester.pump(); + expect(find.byType(Text), findsWidgets); + expect(find.text('Data Successfully Submitted'), findsWidgets); + expect(find.byType(CircularProgressIndicator), findsNothing); + expect(find.byType(SnackBar), findsOneWidget); + }, returnsNormally); + }); + + testWidgets('Validate Error Consumer', (tester) async { + late ${module.toCamelCase()}${submodule.toCamelCase()}Controller controller; + + setUp(() { + controller = ${module.toCamelCase()}${submodule.toCamelCase()}Controller(); + }); + + tearDown(() { + controller.dispose(); + }); + + await controller.run(); + expect(controller.value, isA()); + expect(controller.value.message, equals('Something Went Wrong')); + expect(controller.value.data, isNotNull); + expect(controller.value.data, isA()); + + expect(() async { + await tester.pumpWidget(const MaterialApp(home: ${module.toCamelCase()}${submodule.toCamelCase()}View())); + await tester.pump(); + expect(find.byType(Text), findsWidgets); + expect(find.text('Something Went Wrong'), findsWidgets); + expect(find.byType(CircularProgressIndicator), findsNothing); + expect(find.byType(SnackBar), findsOneWidget); + }, returnsNormally); + }); + }); +} +'''; + } +} diff --git a/bin/src/shared/models/shared_enum.dart b/bin/src/shared/models/shared_enum.dart deleted file mode 100644 index d7b9b8c..0000000 --- a/bin/src/shared/models/shared_enum.dart +++ /dev/null @@ -1,8 +0,0 @@ -part of '../shared.dart'; - -/// The type of the module, either `Model`, `View` or `Controller. -enum SharedType { - models, - views, - controllers; -} diff --git a/bin/src/shared/shared.dart b/bin/src/shared/shared.dart index 9ee1566..88051ef 100644 --- a/bin/src/shared/shared.dart +++ b/bin/src/shared/shared.dart @@ -3,17 +3,19 @@ library shared; import 'dart:io'; import 'package:args/args.dart'; -part 'models/shared_enum.dart'; -part 'models/shared_extension.dart'; -part 'models/shared_runner.dart'; +part 'shared_enum.dart'; +part 'shared_extension.dart'; +part 'shared_runner.dart'; final class Shared extends SharedRunner { const Shared( super.data, { required this.runner, + required this.testRunner, }) : super(type: SharedType.models); final List runner; + final List testRunner; @override List get submodules { @@ -30,6 +32,7 @@ final class Shared extends SharedRunner { // Auto-Generated API Bloc structure // Created at ${DateTime.now()} // 🍔 [Buy me a coffee](https://www.buymeacoffee.com/nialixus) 🚀 +library ${module.toLowerCase()}; import 'package:api_bloc/api_bloc.dart'; import 'package:flutter/material.dart'; @@ -45,10 +48,10 @@ import 'package:flutter/material.dart'; @override void run(StringBuffer buffer) { - final folder = Directory(directory.path.toPath) + Directory folder = Directory(directory.path.toPath) ..createSync(recursive: true); buffer.write('📂 ${folder.path.toPath}\n'); - final file = File('${folder.path.toPath}$module.dart'); + File file = File('${folder.path.toPath}$module.dart'); if (file.existsSync()) { buffer.write('\x1B[30m 📄 ${file.path} \x1B[33m[SKIPPED]\x1B[32m\n'); @@ -58,8 +61,22 @@ import 'package:flutter/material.dart'; ..createSync(recursive: true) ..writeAsStringSync(template(module: module, submodule: '')); } + for (var runner in this.runner) { runner.run(buffer); } + + folder = Directory('${data['output']}' + .toLowerCase() + .toPath + .replaceFirst(RegExp(r'(^|/)\blib/'), 'test/') + + module.toLowerCase().toPath) + ..createSync(recursive: true); + + buffer.write('📂 ${folder.path.toPath}\n'); + + for (var runner in testRunner) { + runner.run(buffer); + } } } diff --git a/bin/src/shared/shared_enum.dart b/bin/src/shared/shared_enum.dart new file mode 100644 index 0000000..efe391c --- /dev/null +++ b/bin/src/shared/shared_enum.dart @@ -0,0 +1,20 @@ +part of 'shared.dart'; + +/// The type of the module, either `Model`, `View` or `Controller. +enum SharedType { + models, + views, + controllers; + + @override + String toString() { + switch (this) { + case SharedType.models: + return 'Model'; + case SharedType.views: + return 'View'; + case SharedType.controllers: + return 'Controller'; + } + } +} diff --git a/bin/src/shared/models/shared_extension.dart b/bin/src/shared/shared_extension.dart similarity index 93% rename from bin/src/shared/models/shared_extension.dart rename to bin/src/shared/shared_extension.dart index 1f80594..6547476 100644 --- a/bin/src/shared/models/shared_extension.dart +++ b/bin/src/shared/shared_extension.dart @@ -1,4 +1,4 @@ -part of '../shared.dart'; +part of 'shared.dart'; extension SharedExtension on String { String get toPath => endsWith('/') ? this : '$this/'; diff --git a/bin/src/shared/models/shared_runner.dart b/bin/src/shared/shared_runner.dart similarity index 92% rename from bin/src/shared/models/shared_runner.dart rename to bin/src/shared/shared_runner.dart index deabfbe..d864e58 100644 --- a/bin/src/shared/models/shared_runner.dart +++ b/bin/src/shared/shared_runner.dart @@ -1,4 +1,4 @@ -part of '../shared.dart'; +part of 'shared.dart'; /// Base view class for all class generator. abstract class SharedRunner { @@ -26,7 +26,7 @@ abstract class SharedRunner { )..createSync(recursive: true); } - /// Execute and create the view into the [directory]. + /// Execute to create the template and transform it into a file. void run(StringBuffer buffer) { final folder = Directory('${directory.path.toPath}${type.name.toLowerCase()}') @@ -47,7 +47,7 @@ abstract class SharedRunner { } } - /// Template for the view. + /// Template for the generated file. String template({ required String module, required String submodule, diff --git a/bin/src/write/controllers/write_controller_test.dart b/bin/src/write/controllers/write_controller_test.dart new file mode 100644 index 0000000..295f998 --- /dev/null +++ b/bin/src/write/controllers/write_controller_test.dart @@ -0,0 +1,90 @@ +part of '../write.dart'; + +class WriteControllerTest extends SharedRunner { + WriteControllerTest( + super.data, { + super.type = SharedType.controllers, + }); + + @override + Directory get directory { + return Directory( + '${data['output']}' + .toLowerCase() + .toPath + .replaceFirst(RegExp(r'(^|/)\blib/'), 'test/') + + module.toLowerCase().toPath, + )..createSync(recursive: true); + } + + @override + List get submodules { + return data['write']; + } + + @override + String template({ + required String module, + required String submodule, + }) { + return ''' +// ignore: avoid_relative_lib_imports +import '../../../../${directory.path.replaceFirst(RegExp(r'(^|/)\btest/'), 'lib/')}/${module.toLowerCase()}.dart'; +import 'package:api_bloc/api_bloc.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('${module.toCamelCase()}${submodule.toCamelCase()}Controller', () { + late ${module.toCamelCase()}${submodule.toCamelCase()}Controller controller; + + setUp(() { + controller = ${module.toCamelCase()}${submodule.toCamelCase()}Controller(); + }); + + tearDown(() { + controller.dispose(); + }); + + test('Validate Initial State', () async { + await controller.run(); + expect(controller.value, isA()); + expect(controller.value.data, isNull); + expect(controller.value.message, equals('Waiting For Interaction')); + }); + + + test('Validate Loading State', () async { + await controller.run(); + expect(controller.value, isA()); + expect(controller.value.data, isNull); + expect(controller.value.message, equals('Fetching On Progress')); + }); + + test('Validate Success State', () async { + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isA<${module.toCamelCase()}${submodule.toCamelCase()}SuccessModel>()); + expect(controller.value.message, equals('Data Successfully Fetched')); + }); + + test('Validate Failed State', () async { + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isA<${module.toCamelCase()}${submodule.toCamelCase()}FailedModel>()); + expect(controller.value.message, equals('Submitted Data Returns Failed')); + }); + + test('Validate Error State', () async { + await controller.run(); + expect(controller.value, isA()); + expect(controller.value.message, equals('Something Went Wrong')); + expect(controller.value.data, isNotNull); + expect(controller.value.data, isA()); + }); + }); +} +'''; + } +} diff --git a/bin/src/write/models/write_model_test.dart b/bin/src/write/models/write_model_test.dart new file mode 100644 index 0000000..b316974 --- /dev/null +++ b/bin/src/write/models/write_model_test.dart @@ -0,0 +1,50 @@ +part of '../write.dart'; + +class WriteModelTest extends SharedRunner { + WriteModelTest( + super.data, { + super.type = SharedType.models, + }); + + @override + Directory get directory { + return Directory( + '${data['output']}' + .toLowerCase() + .toPath + .replaceFirst(RegExp(r'(^|/)\blib/'), 'test/') + + module.toLowerCase().toPath, + )..createSync(recursive: true); + } + + @override + List get submodules { + return data['write']; + } + + @override + String template({ + required String module, + required String submodule, + }) { + return ''' +// ignore: avoid_relative_lib_imports +import '../../../../${directory.path.replaceFirst(RegExp(r'(^|/)\btest/'), 'lib/')}/${module.toLowerCase()}.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('${module.toCamelCase()}${submodule.toCamelCase()}Model', () { + test('Validate Success Type', () { + const ${module.toCamelCase()}${submodule.toCamelCase()}SuccessModel data = ${module.toCamelCase()}${submodule.toCamelCase()}SuccessModel.test(); + expect(data, isA<${module.toCamelCase()}${submodule.toCamelCase()}SuccessModel>()); + }); + + test('Validate Failed Type', () { + const ${module.toCamelCase()}${submodule.toCamelCase()}FailedModel data = ${module.toCamelCase()}${submodule.toCamelCase()}FailedModel.test(); + expect(data, isA<${module.toCamelCase()}${submodule.toCamelCase()}FailedModel>()); + }); + }); +} +'''; + } +} diff --git a/bin/src/write/views/write_view.dart b/bin/src/write/views/write_view.dart index 2c9a665..6376562 100644 --- a/bin/src/write/views/write_view.dart +++ b/bin/src/write/views/write_view.dart @@ -19,8 +19,8 @@ final class WriteView extends SharedRunner { return ''' part of '../$module.dart'; -class ${module.toCamelCase()}${submodule.toCamelCase()}${type.name.toCamelCase()} extends StatelessWidget { - const ${module.toCamelCase()}${submodule.toCamelCase()}${type.name.toCamelCase()}({super.key}); +class ${module.toCamelCase()}${submodule.toCamelCase()}${type.toString().toCamelCase()} extends StatelessWidget { + const ${module.toCamelCase()}${submodule.toCamelCase()}${type.toString().toCamelCase()}({super.key}); @override Widget build(BuildContext context) { diff --git a/bin/src/write/views/write_view_test.dart b/bin/src/write/views/write_view_test.dart new file mode 100644 index 0000000..026ad5d --- /dev/null +++ b/bin/src/write/views/write_view_test.dart @@ -0,0 +1,177 @@ +part of '../write.dart'; + +class WriteViewTest extends SharedRunner { + WriteViewTest( + super.data, { + super.type = SharedType.views, + }); + + @override + Directory get directory { + return Directory( + '${data['output']}' + .toLowerCase() + .toPath + .replaceFirst(RegExp(r'(^|/)\blib/'), 'test/') + + module.toLowerCase().toPath, + )..createSync(recursive: true); + } + + @override + List get submodules { + return data['write']; + } + + @override + String template({ + required String module, + required String submodule, + }) { + return ''' +// ignore: avoid_relative_lib_imports +import '../../../../${directory.path.replaceFirst(RegExp(r'(^|/)\btest/'), 'lib/')}/${module.toLowerCase()}.dart'; +import 'package:api_bloc/api_bloc.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('${module.toCamelCase()}${submodule.toCamelCase()}View', () { + testWidgets('Validate Initial Consumer', (tester) async { + late ${module.toCamelCase()}${submodule.toCamelCase()}Controller controller; + + setUp(() { + controller = ${module.toCamelCase()}${submodule.toCamelCase()}Controller(); + }); + + tearDown(() { + controller.dispose(); + }); + + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isNull); + expect(controller.value.message, equals('Waiting For Interaction')); + + expect(() async { + await tester.pumpWidget(const MaterialApp(home: ${module.toCamelCase()}${submodule.toCamelCase()}View())); + await tester.pump(); + expect(find.byType(Text), findsOneWidget); + expect(find.text('Waiting For Interaction'), findsOneWidget); + expect(find.byType(CircularProgressIndicator), findsNothing); + expect(find.byType(SnackBar), findsNothing); + }, returnsNormally); + }); + + testWidgets('Validate Loading Consumer', (tester) async { + late ${module.toCamelCase()}${submodule.toCamelCase()}Controller controller; + + setUp(() { + controller = ${module.toCamelCase()}${submodule.toCamelCase()}Controller(); + }); + + tearDown(() { + controller.dispose(); + }); + + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isNull); + expect(controller.value.message, equals('Submitting In Progress')); + + expect(() async { + await tester.pumpWidget(const MaterialApp(home: ${module.toCamelCase()}${submodule.toCamelCase()}View())); + await tester.pump(); + expect(find.byType(Text), findsNothing); + expect(find.text('Submitting In Progress'), findsNothing); + expect(find.byType(CircularProgressIndicator), findsOneWidget); + expect(find.byType(SnackBar), findsNothing); + }, returnsNormally); + }); + + testWidgets('Validate Success Consumer', (tester) async { + late ${module.toCamelCase()}${submodule.toCamelCase()}Controller controller; + + setUp(() { + controller = ${module.toCamelCase()}${submodule.toCamelCase()}Controller(); + }); + + tearDown(() { + controller.dispose(); + }); + + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isA<${module.toCamelCase()}${submodule.toCamelCase()}SuccessModel>()); + expect(controller.value.message, equals('Data Successfully Submitted')); + + expect(() async { + await tester.pumpWidget(const MaterialApp(home: ${module.toCamelCase()}${submodule.toCamelCase()}View())); + await tester.pump(); + expect(find.byType(Text), findsWidgets); + expect(find.text('Data Successfully Submitted'), findsWidgets); + expect(find.byType(CircularProgressIndicator), findsNothing); + expect(find.byType(SnackBar), findsOneWidget); + }, returnsNormally); + }); + + testWidgets('Validate Failed Consumer', (tester) async { + late ${module.toCamelCase()}${submodule.toCamelCase()}Controller controller; + + setUp(() { + controller = ${module.toCamelCase()}${submodule.toCamelCase()}Controller(); + }); + + tearDown(() { + controller.dispose(); + }); + + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isA<${module.toCamelCase()}${submodule.toCamelCase()}FailedModel>()); + expect(controller.value.message, equals('Submitted Data Returns Failed')); + + expect(() async { + await tester.pumpWidget(const MaterialApp(home: ${module.toCamelCase()}${submodule.toCamelCase()}View())); + await tester.pump(); + expect(find.byType(Text), findsWidgets); + expect(find.text('Submitted Data Returns Failed'), findsWidgets); + expect(find.byType(CircularProgressIndicator), findsNothing); + expect(find.byType(SnackBar), findsOneWidget); + }, returnsNormally); + }); + + testWidgets('Validate Error Consumer', (tester) async { + late ${module.toCamelCase()}${submodule.toCamelCase()}Controller controller; + + setUp(() { + controller = ${module.toCamelCase()}${submodule.toCamelCase()}Controller(); + }); + + tearDown(() { + controller.dispose(); + }); + + await controller.run(); + expect(controller.value, isA()); + expect(controller.value.message, equals('Something Went Wrong')); + expect(controller.value.data, isNotNull); + expect(controller.value.data, isA()); + + expect(() async { + await tester.pumpWidget(const MaterialApp(home: ${module.toCamelCase()}${submodule.toCamelCase()}View())); + await tester.pump(); + expect(find.byType(Text), findsWidgets); + expect(find.text('Something Went Wrong'), findsWidgets); + expect(find.byType(CircularProgressIndicator), findsNothing); + expect(find.byType(SnackBar), findsOneWidget); + }, returnsNormally); + }); + }); +} +'''; + } +} diff --git a/bin/src/write/write.dart b/bin/src/write/write.dart index 3d186a3..607a064 100644 --- a/bin/src/write/write.dart +++ b/bin/src/write/write.dart @@ -1,7 +1,12 @@ library write; +import 'dart:io'; + import '../shared/shared.dart'; +part 'controllers/write_controller_test.dart'; part 'controllers/write_controller.dart'; +part 'models/write_model_test.dart'; part 'models/write_model.dart'; +part 'views/write_view_test.dart'; part 'views/write_view.dart'; diff --git a/example/lib/main.dart b/example/lib/main.dart index 0598ce4..c82e63a 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -28,7 +28,8 @@ class HomePage extends StatelessWidget { alignment: Alignment.center, color: Colors.blue, child: TextButton( - onPressed: () => context.to(const [GetPage(), PostPage()][i]), + onPressed: () => + context.to(const [GetUserView(), CreateUserView()][i]), child: Text( ["GET Request", "POST Request"][i], textAlign: TextAlign.center, diff --git a/example/lib/src/get/get.dart b/example/lib/src/get/get.dart index dbd0047..781dac2 100644 --- a/example/lib/src/get/get.dart +++ b/example/lib/src/get/get.dart @@ -6,4 +6,4 @@ import 'package:flutter/material.dart'; part 'controllers/get_controller.dart'; part 'models/get_model.dart'; -part 'views/get_page.dart'; +part 'views/get_view.dart'; diff --git a/example/lib/src/get/views/get_page.dart b/example/lib/src/get/views/get_view.dart similarity index 94% rename from example/lib/src/get/views/get_page.dart rename to example/lib/src/get/views/get_view.dart index f3be341..b209cb1 100644 --- a/example/lib/src/get/views/get_page.dart +++ b/example/lib/src/get/views/get_view.dart @@ -1,7 +1,7 @@ part of '../get.dart'; -class GetPage extends StatelessWidget { - const GetPage({super.key}); +class GetUserView extends StatelessWidget { + const GetUserView({super.key}); @override Widget build(BuildContext context) { diff --git a/example/lib/src/post/post.dart b/example/lib/src/post/post.dart index fa80045..ffaba12 100644 --- a/example/lib/src/post/post.dart +++ b/example/lib/src/post/post.dart @@ -7,4 +7,4 @@ import 'package:flutter/material.dart'; part 'controllers/post_controller.dart'; part 'models/post_model.dart'; -part 'views/post_page.dart'; +part 'views/post_view.dart'; diff --git a/example/lib/src/post/views/post_page.dart b/example/lib/src/post/views/post_view.dart similarity index 97% rename from example/lib/src/post/views/post_page.dart rename to example/lib/src/post/views/post_view.dart index 5615ca2..23562d4 100644 --- a/example/lib/src/post/views/post_page.dart +++ b/example/lib/src/post/views/post_view.dart @@ -1,7 +1,7 @@ part of '../post.dart'; -class PostPage extends StatelessWidget { - const PostPage({super.key}); +class CreateUserView extends StatelessWidget { + const CreateUserView({super.key}); @override Widget build(BuildContext context) { diff --git a/example/lib/src_generated_template/auth/auth.dart b/example/lib/src_generated_template/auth/auth.dart deleted file mode 100644 index ded4fff..0000000 --- a/example/lib/src_generated_template/auth/auth.dart +++ /dev/null @@ -1,13 +0,0 @@ -// Auto-Generated API Bloc structure -// Created at 2024-06-02 08:51:05.470451 -// 🍔 [Buy me a coffee](https://www.buymeacoffee.com/nialixus) 🚀 - -import 'package:api_bloc/api_bloc.dart'; -import 'package:flutter/material.dart'; - -part 'models/auth_data.dart'; -part 'models/auth_update.dart'; -part 'views/auth_data.dart'; -part 'views/auth_update.dart'; -part 'controllers/auth_data.dart'; -part 'controllers/auth_update.dart'; \ No newline at end of file diff --git a/example/lib/src_generated_template/auth/controllers/auth_data.dart b/example/lib/src_generated_template/auth/controllers/auth_data.dart deleted file mode 100644 index db2a80a..0000000 --- a/example/lib/src_generated_template/auth/controllers/auth_data.dart +++ /dev/null @@ -1,12 +0,0 @@ -part of '../auth.dart'; - -class AuthDataController extends ReadController { - @override - Future onRequest(Map args) async { - // Delay to make the loading state more noticable. - await Future.delayed(const Duration(milliseconds: 300)); - - // Emit your success state here ↓↓ - emit(const ReadSuccessState(data: AuthDataModel.test())); - } -} diff --git a/example/lib/src_generated_template/auth/controllers/auth_update.dart b/example/lib/src_generated_template/auth/controllers/auth_update.dart deleted file mode 100644 index a7f8866..0000000 --- a/example/lib/src_generated_template/auth/controllers/auth_update.dart +++ /dev/null @@ -1,18 +0,0 @@ -part of '../auth.dart'; - -class AuthUpdateController extends WriteController { - @override - Future onRequest(Map args) async { - // Delay to make the loading state more noticable. - await Future.delayed(const Duration(milliseconds: 300)); - - // Emit your success and failed state here ↓↓ - if (args['success'] ?? false) { - emit(const WriteSuccessState( - data: AuthUpdateSuccessModel.test())); - } else { - emit(const WriteFailedState( - data: AuthUpdateFailedModel.test())); - } - } -} diff --git a/example/lib/src_generated_template/auth/models/auth_data.dart b/example/lib/src_generated_template/auth/models/auth_data.dart deleted file mode 100644 index 6c18265..0000000 --- a/example/lib/src_generated_template/auth/models/auth_data.dart +++ /dev/null @@ -1,5 +0,0 @@ -part of '../auth.dart'; - -class AuthDataModel { - const AuthDataModel.test(); -} diff --git a/example/lib/src_generated_template/auth/models/auth_update.dart b/example/lib/src_generated_template/auth/models/auth_update.dart deleted file mode 100644 index b076c9e..0000000 --- a/example/lib/src_generated_template/auth/models/auth_update.dart +++ /dev/null @@ -1,10 +0,0 @@ -part of '../auth.dart'; - -class AuthUpdateSuccessModel { - const AuthUpdateSuccessModel.test(); -} - -class AuthUpdateFailedModel { - const AuthUpdateFailedModel.test(); -} - diff --git a/example/lib/src_generated_template/auth/views/auth_data.dart b/example/lib/src_generated_template/auth/views/auth_data.dart deleted file mode 100644 index d51b09b..0000000 --- a/example/lib/src_generated_template/auth/views/auth_data.dart +++ /dev/null @@ -1,19 +0,0 @@ -part of '../auth.dart'; - -class AuthDataViews extends StatelessWidget { - const AuthDataViews({super.key}); - - @override - Widget build(BuildContext context) { - return ApiBloc( - controller: AuthDataController(), - child: BlocBuilder( - builder: (context, state, child) { - if (state is ReadSuccessState) { - } else if (state is ReadErrorState) {} - return Text(state.message); - }, - ), - ); - } -} diff --git a/example/lib/src_generated_template/auth/views/auth_update.dart b/example/lib/src_generated_template/auth/views/auth_update.dart deleted file mode 100644 index c00d214..0000000 --- a/example/lib/src_generated_template/auth/views/auth_update.dart +++ /dev/null @@ -1,23 +0,0 @@ -part of '../auth.dart'; - -class AuthUpdateViews extends StatelessWidget { - const AuthUpdateViews({super.key}); - - @override - Widget build(BuildContext context) { - return ApiBloc( - controller: AuthUpdateController(), - child: BlocConsumer( - listener: (context, state) { - if (state is WriteSuccessState) { - } else if (state is WriteFailedState) { - } else if (state is WriteErrorState) {} - }, - builder: (context, state, child) { - if (state is WriteLoadingState) {} - return Text(state.message); - }, - ), - ); - } -} diff --git a/example/lib/src_generated_template/user/controllers/user_data.dart b/example/lib/src_generated_template/user/controllers/user_data.dart deleted file mode 100644 index 4dfd124..0000000 --- a/example/lib/src_generated_template/user/controllers/user_data.dart +++ /dev/null @@ -1,12 +0,0 @@ -part of '../user.dart'; - -class UserDataController extends ReadController { - @override - Future onRequest(Map args) async { - // Delay to make the loading state more noticable. - await Future.delayed(const Duration(milliseconds: 300)); - - // Emit your success state here ↓↓ - emit(const ReadSuccessState(data: UserDataModel.test())); - } -} diff --git a/example/lib/src_generated_template/user/controllers/user_update.dart b/example/lib/src_generated_template/user/controllers/user_update.dart deleted file mode 100644 index 97ef7a8..0000000 --- a/example/lib/src_generated_template/user/controllers/user_update.dart +++ /dev/null @@ -1,18 +0,0 @@ -part of '../user.dart'; - -class UserUpdateController extends WriteController { - @override - Future onRequest(Map args) async { - // Delay to make the loading state more noticable. - await Future.delayed(const Duration(milliseconds: 300)); - - // Emit your success and failed state here ↓↓ - if (args['success'] ?? false) { - emit(const WriteSuccessState( - data: UserUpdateSuccessModel.test())); - } else { - emit(const WriteFailedState( - data: UserUpdateFailedModel.test())); - } - } -} diff --git a/example/lib/src_generated_template/user/models/user_data.dart b/example/lib/src_generated_template/user/models/user_data.dart deleted file mode 100644 index bfd5c4a..0000000 --- a/example/lib/src_generated_template/user/models/user_data.dart +++ /dev/null @@ -1,5 +0,0 @@ -part of '../user.dart'; - -class UserDataModel { - const UserDataModel.test(); -} diff --git a/example/lib/src_generated_template/user/models/user_update.dart b/example/lib/src_generated_template/user/models/user_update.dart deleted file mode 100644 index 7777439..0000000 --- a/example/lib/src_generated_template/user/models/user_update.dart +++ /dev/null @@ -1,9 +0,0 @@ -part of '../user.dart'; - -class UserUpdateSuccessModel { - const UserUpdateSuccessModel.test(); -} - -class UserUpdateFailedModel { - const UserUpdateFailedModel.test(); -} diff --git a/example/lib/src_generated_template/user/user.dart b/example/lib/src_generated_template/user/user.dart deleted file mode 100644 index f9632f0..0000000 --- a/example/lib/src_generated_template/user/user.dart +++ /dev/null @@ -1,14 +0,0 @@ -// Auto-Generated API Bloc structure -// Created at 2024-06-01 11:30:58.447124 -// 🍔 [Buy me a coffee](https://www.buymeacoffee.com/nialixus) 🚀 -library user; - -import 'package:api_bloc/api_bloc.dart'; -import 'package:flutter/material.dart'; - -part 'controllers/user_data.dart'; -part 'models/user_data.dart'; -part 'views/user_data.dart'; -part 'controllers/user_update.dart'; -part 'models/user_update.dart'; -part 'views/user_update.dart'; diff --git a/example/lib/src_generated_template/user/views/user_data.dart b/example/lib/src_generated_template/user/views/user_data.dart deleted file mode 100644 index e8c3974..0000000 --- a/example/lib/src_generated_template/user/views/user_data.dart +++ /dev/null @@ -1,19 +0,0 @@ -part of '../user.dart'; - -class UserDataView extends StatelessWidget { - const UserDataView({super.key}); - - @override - Widget build(BuildContext context) { - return ApiBloc( - controller: UserDataController(), - child: BlocBuilder( - builder: (context, state, child) { - if (state is ReadSuccessState) { - } else if (state is ReadErrorState) {} - return Text(state.message); - }, - ), - ); - } -} diff --git a/example/lib/src_generated_template/user/views/user_update.dart b/example/lib/src_generated_template/user/views/user_update.dart deleted file mode 100644 index d632c43..0000000 --- a/example/lib/src_generated_template/user/views/user_update.dart +++ /dev/null @@ -1,23 +0,0 @@ -part of '../user.dart'; - -class UserUpdateView extends StatelessWidget { - const UserUpdateView({super.key}); - - @override - Widget build(BuildContext context) { - return ApiBloc( - controller: UserUpdateController(), - child: BlocConsumer( - listener: (context, state) { - if (state is WriteSuccessState) { - } else if (state is WriteFailedState) { - } else if (state is WriteErrorState) {} - }, - builder: (context, state, child) { - if (state is WriteLoadingState) {} - return Text(state.message); - }, - ), - ); - } -} diff --git a/example/test/src/get/controllers/get_controller.dart b/example/test/src/get/controllers/get_controller.dart new file mode 100644 index 0000000..1443342 --- /dev/null +++ b/example/test/src/get/controllers/get_controller.dart @@ -0,0 +1,55 @@ +import 'package:api_bloc/api_bloc.dart'; +import 'package:example/src/get/get.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('GetUserController', () { + late GetUserController controller; + + setUp(() { + controller = GetUserController(); + }); + + tearDown(() { + controller.dispose(); + }); + + // test('Validate Initial State', () async { + // await controller.run(); + // expect(controller.value, isA()); + // expect(controller.value.data, isNull); + // expect(controller.value.message, equals('Waiting For Interaction')); + // }); + + test('Validate Loading State', () async { + await controller.run(); + expect(controller.value, isA()); + expect(controller.value.data, isNull); + expect(controller.value.message, equals('Fetching On Progress')); + }); + + test('Validate Success State', () async { + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isA()); + expect(controller.value.message, equals('Data Successfully Fetched')); + }); + + // test('Validate Failed State', () async { + // await controller.run(); + // expect(controller.value, isA()); + // expect(controller.value, isA>()); + // expect(controller.value.data, isA()); + // expect(controller.value.message, equals('Submitted Data Returns Failed')); + // }); + + test('Validate Error State', () async { + await controller.run(); + expect(controller.value, isA()); + expect(controller.value.message, equals('Something Went Wrong')); + expect(controller.value.data, isNotNull); + expect(controller.value.data, isA()); + }); + }); +} diff --git a/example/test/src/get/models/get_model.dart b/example/test/src/get/models/get_model.dart new file mode 100644 index 0000000..b2cfb15 --- /dev/null +++ b/example/test/src/get/models/get_model.dart @@ -0,0 +1,15 @@ +import 'package:example/src/get/get.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('GetUserModel', () { + test('Validate Type', () { + const GetUserModel data = GetUserModel( + id: 0, + firstName: 'firstName', + lastName: 'lastName', + avatar: 'avatar'); + expect(data, isA()); + }); + }); +} diff --git a/example/test/src/get/views/get_view.dart b/example/test/src/get/views/get_view.dart new file mode 100644 index 0000000..295d668 --- /dev/null +++ b/example/test/src/get/views/get_view.dart @@ -0,0 +1,143 @@ +import 'package:api_bloc/api_bloc.dart'; +import 'package:example/src/get/get.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('BlocConsumer', () { + // testWidgets('Validate Initial Consumer', (tester) async { + // late GetUserController controller; + + // setUp(() { + // controller = GetUserController(); + // }); + + // tearDown(() { + // controller.dispose(); + // }); + + // await controller.run(); + // expect(controller.value, isA()); + // expect(controller.value, isA>()); + // expect(controller.value.data, isNull); + // expect(controller.value.message, equals('Waiting For Interaction')); + + // expect(() async { + // await tester.pumpWidget(const MaterialApp(home: GetUserView())); + // await tester.pump(); + // expect(find.byType(Text), findsOneWidget); + // expect(find.text('Waiting For Interaction'), findsOneWidget); + // expect(find.byType(CircularProgressIndicator), findsNothing); + // expect(find.byType(SnackBar), findsNothing); + // }, returnsNormally); + // }); + + testWidgets('Validate Loading Consumer', (tester) async { + late GetUserController controller; + + setUp(() { + controller = GetUserController(); + }); + + tearDown(() { + controller.dispose(); + }); + + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isNull); + expect(controller.value.message, equals('Submitting In Progress')); + + expect(() async { + await tester.pumpWidget(const MaterialApp(home: GetUserView())); + await tester.pump(); + expect(find.byType(Text), findsNothing); + expect(find.text('Submitting In Progress'), findsNothing); + expect(find.byType(CircularProgressIndicator), findsOneWidget); + expect(find.byType(SnackBar), findsNothing); + }, returnsNormally); + }); + + testWidgets('Validate Success Consumer', (tester) async { + late GetUserController controller; + + setUp(() { + controller = GetUserController(); + }); + + tearDown(() { + controller.dispose(); + }); + + await controller.run(); + expect(controller.value, isA()); + expect(controller.value, isA>()); + expect(controller.value.data, isA()); + expect(controller.value.message, equals('Data Successfully Submitted')); + + expect(() async { + await tester.pumpWidget(const MaterialApp(home: GetUserView())); + await tester.pump(); + expect(find.byType(Text), findsWidgets); + expect(find.text('Data Successfully Submitted'), findsWidgets); + expect(find.byType(CircularProgressIndicator), findsNothing); + expect(find.byType(SnackBar), findsOneWidget); + }, returnsNormally); + }); + + // testWidgets('Validate Failed Consumer', (tester) async { + // late GetUserController controller; + + // setUp(() { + // controller = GetUserController(); + // }); + + // tearDown(() { + // controller.dispose(); + // }); + + // await controller.run(); + // expect(controller.value, isA()); + // expect(controller.value, isA>()); + // expect(controller.value.data, isA()); + // expect(controller.value.message, equals('Submitted Data Returns Failed')); + + // expect(() async { + // await tester.pumpWidget(const MaterialApp(home: GetUserView())); + // await tester.pump(); + // expect(find.byType(Text), findsWidgets); + // expect(find.text('Submitted Data Returns Failed'), findsWidgets); + // expect(find.byType(CircularProgressIndicator), findsNothing); + // expect(find.byType(SnackBar), findsOneWidget); + // }, returnsNormally); + // }); + + testWidgets('Validate Error Consumer', (tester) async { + late GetUserController controller; + + setUp(() { + controller = GetUserController(); + }); + + tearDown(() { + controller.dispose(); + }); + + await controller.run(); + expect(controller.value, isA()); + expect(controller.value.message, equals('Something Went Wrong')); + expect(controller.value.data, isNotNull); + expect(controller.value.data, isA()); + + expect(() async { + await tester.pumpWidget(const MaterialApp(home: GetUserView())); + await tester.pump(); + expect(find.byType(Text), findsWidgets); + expect(find.text('Something Went Wrong'), findsWidgets); + expect(find.byType(CircularProgressIndicator), findsNothing); + expect(find.byType(SnackBar), findsOneWidget); + }, returnsNormally); + }); + }); +}