diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3dfa975..282e410 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -86,10 +86,10 @@ jobs: run: dart pub publish --dry-run - name: 📊 Check Code Coverage - uses: VeryGoodOpenSource/very_good_coverage@v2 + uses: VeryGoodOpenSource/very_good_coverage@v3 with: path: "./coverage/lcov.info" - min_coverage: 99 + min_coverage: 100 - name: ⬆️ Upload Coverage to Coveralls uses: coverallsapp/github-action@v2.2.3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d0f889..1e8ac8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [3.0.0] - 2024-03-26 + +### Changed - 3.0.0 + +* **Dependency**: Updated the `dio` package version from `5.4.1` to `5.4.2`. +* **Dependency**: Updated the `connectivity_plus` plugin from version `^5.0.2` to `^6.0.1`. + +### Breaking Changes - 3.0.0 + +* **SDK and Flutter versions**: + Increased the minimum Dart version from `>=3.0.0 <4.0.0` to `>=3.3.0 <4.0.0` and the Flutter version from `>=3.0.0` to `>=3.19.0` in the `pubspec.yaml` file. This change may affect developers working on older versions of the SDK or Flutter. + +### Added - 3.0.0 + +* **Code Quality**: Enhanced linter rules for improved code quality, enabling previously commented-out linting rules, adding new ones, and notably, the addition of metrics with specific complexity parameters to drive better code practices. + ## [2.0.2] - 2024-03-11 Overall, these changes primarily revolve around improving exception handling and string formatting versatility. @@ -49,7 +65,7 @@ Overall, these changes primarily revolve around improving exception handling and ## [2.0.0] - 2024-03-10 -### Breaking Changes +### Breaking Changes - 2.0.0 Refactor of Exception Handling: The conversion of DioExceptionHandler into a mixin and the static method adjustments represent a breaking change for any existing codebases that instantiate DioExceptionHandler or rely on its previous class structure. Projects will need to update their exception handling implementations to adapt to this refactor. This change aims to streamline the process and enhance overall usability, but will require attention during migration to the new version. diff --git a/analysis_options.yaml b/analysis_options.yaml index 56f2547..7e1a230 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -12,6 +12,10 @@ analyzer: implicit-casts: false implicit-dynamic: false + exclude: + - lib/**/*.g.dart + - lib/generated/*.g.dart + # Lint rules and documentation, see http://dart-lang.github.io/linter/lints linter: rules: @@ -64,7 +68,10 @@ linter: - prefer_const_literals_to_create_immutables - prefer_constructors_over_static_methods - prefer_expression_function_bodies + - prefer_final_fields + - prefer_final_in_for_each - prefer_final_locals + - prefer_final_parameters - prefer_foreach - prefer_single_quotes # - public_member_api_docs # TODO: Update Docs @@ -87,10 +94,10 @@ dart_code_linter: # - package:dart_code_linter/presets/all.yaml # - package:dart_code_linter/presets/intl.yaml - # metrics: - # cyclomatic-complexity: 20 - # number-of-parameters: 4 - # maximum-nesting-level: 5 + metrics: + cyclomatic-complexity: 20 + number-of-parameters: 4 + maximum-nesting-level: 5 metrics-exclude: - test/** @@ -110,22 +117,19 @@ dart_code_linter: - did-update-widget-method - dispose-method # - format-comment: true - - no-magic-number: - allowed: [0, 2, 100, 200, 300, 400, 401, 402, 403, 404, 500, 501, 600] - # - allow-only-once: true # - avoid-dynamic: true - # - avoid-passing-async-when-sync-expected: true - # - avoid-redundant-async: true - # - avoid-unnecessary-type-assertions: true - # - avoid-unnecessary-type-casts: true - # - avoid-unrelated-type-assertions: true - # - avoid-unused-parameters: true + - avoid-passing-async-when-sync-expected: true + - avoid-redundant-async: true + - avoid-unnecessary-type-assertions: true + - avoid-unnecessary-type-casts: true + - avoid-unrelated-type-assertions: true + - avoid-unused-parameters: true # - avoid-nested-conditional-expressions: true - # - newline-before-return: true - # - no-boolean-literal-compare: true - # - no-empty-block: true - # - prefer-trailing-comma: true - # - prefer-conditional-expressions: true - # - no-equal-then-else: true - # - prefer-moving-to-variable: true - # - prefer-match-file-name: true \ No newline at end of file + - newline-before-return: true + - no-boolean-literal-compare: true + - no-empty-block: true + - prefer-trailing-comma: true + - prefer-conditional-expressions: true + - no-equal-then-else: true + - prefer-moving-to-variable: true + # - prefer-match-file-name: true diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift index c62a8be..ad535f5 100644 --- a/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,5 +8,5 @@ import Foundation import connectivity_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) + ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) } diff --git a/example/pubspec.lock b/example/pubspec.lock index 356cbe5..ef09107 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -53,18 +53,18 @@ packages: dependency: transitive description: name: connectivity_plus - sha256: "224a77051d52a11fbad53dd57827594d3bd24f945af28bd70bab376d68d437f0" + sha256: e9feae83b1849f61bad9f6f33ee00646e3410d54ce0821e02f262f9901dad3c9 url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "6.0.1" connectivity_plus_platform_interface: dependency: transitive description: name: connectivity_plus_platform_interface - sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a + sha256: b6a56efe1e6675be240de39107281d4034b64ac23438026355b4234042a35adb url: "https://pub.dev" source: hosted - version: "1.2.4" + version: "2.0.0" cupertino_icons: dependency: "direct main" description: @@ -85,10 +85,10 @@ packages: dependency: "direct main" description: name: dio - sha256: "49af28382aefc53562459104f64d16b9dfd1e8ef68c862d5af436cc8356ce5a8" + sha256: "50fec96118958b97c727d0d8f67255d3683f16cc1f90d9bc917b5d4fe3abeca9" url: "https://pub.dev" source: hosted - version: "5.4.1" + version: "5.4.2" equatable: dependency: transitive description: @@ -103,7 +103,7 @@ packages: path: ".." relative: true source: path - version: "2.0.2" + version: "3.0.0" fake_async: dependency: transitive description: @@ -167,14 +167,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.3.0" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" leak_tracker: dependency: transitive description: @@ -340,6 +332,14 @@ packages: url: "https://pub.dev" source: hosted version: "13.0.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" xml: dependency: transitive description: @@ -349,5 +349,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.3.0-279.1.beta <4.0.0" - flutter: ">=3.10.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/lib/src/exception_handler/exception_handler_client.dart b/lib/src/exception_handler/client_exception_handler.dart similarity index 77% rename from lib/src/exception_handler/exception_handler_client.dart rename to lib/src/exception_handler/client_exception_handler.dart index 7b62271..46cb425 100644 --- a/lib/src/exception_handler/exception_handler_client.dart +++ b/lib/src/exception_handler/client_exception_handler.dart @@ -16,16 +16,16 @@ abstract class ClientExceptionHandler { /// ExceptionState and parsed data. /// Future> callApi( - ApiHandler apiHandler, { - HandleHttpParseResponse? handleHttpParseResponse, + final ApiHandler apiHandler, { + final HandleHttpParseResponse? handleHttpParseResponse, }); /// Method [callApi] is a generic method to handle API calls and return a tuple of /// ExceptionState and parsed data. /// static Future> callApi_( - ApiHandler apiHandler, { - HandleHttpParseResponse? handleHttpParseResponse, + final ApiHandler apiHandler, { + final HandleHttpParseResponse? handleHttpParseResponse, }) async { throw UnimplementedError(); } diff --git a/lib/src/exception_handler/dio/dio.dart b/lib/src/exception_handler/dio/dio.dart index 39044e6..1ea3651 100644 --- a/lib/src/exception_handler/dio/dio.dart +++ b/lib/src/exception_handler/dio/dio.dart @@ -2,5 +2,5 @@ // All rights reserved. Use of this source code // is governed by a Apache-2.0 license that can be found in the LICENSE file. +export 'dio_exception_handler.dart'; export 'dio_http_response_extension.dart'; -export 'exception_handler_dio.dart'; diff --git a/lib/src/exception_handler/dio/exception_handler_dio.dart b/lib/src/exception_handler/dio/dio_exception_handler.dart similarity index 91% rename from lib/src/exception_handler/dio/exception_handler_dio.dart rename to lib/src/exception_handler/dio/dio_exception_handler.dart index 45322d8..9cb8a8f 100644 --- a/lib/src/exception_handler/dio/exception_handler_dio.dart +++ b/lib/src/exception_handler/dio/dio_exception_handler.dart @@ -16,8 +16,8 @@ import '../../../exception_handler.dart'; /// any parsing exceptions. /// Future> handleHttpGenericParseResponseDio( - int statusCode, - ResponseParser responseParser, + final int statusCode, + final ResponseParser responseParser, ) async { try { return FailureState( @@ -48,7 +48,7 @@ Future> handleHttpGenericParseResponseDio( /// Method [handleHttp2xxParseResponseDio] tries to parse the response and handle /// any parsing exceptions. Future> handleHttp2xxParseResponseDio( - ResponseParser, TModel> responseParser, + final ResponseParser, TModel> responseParser, ) async { try { final TModel dataModelParsed = await compute( @@ -59,7 +59,7 @@ Future> handleHttp2xxParseResponseDio( return SuccessState(dataModelParsed); } catch (e) { try { - // TODO(andgar2010): need more investigation about compute error on platform windows + // TODO(andgar2010): need more investigation about compute error on platform windows. log( ''' Handle error compute. @@ -123,8 +123,8 @@ class DioExceptionHandler implements ClientExceptionHandler { /// {@endtemplate} @override Future> callApi( - ApiHandler apiHandler, { - HandleHttpParseResponse? handleHttpParseResponse, + final ApiHandler apiHandler, { + final HandleHttpParseResponse? handleHttpParseResponse, }) async { handleParseResponse_ = handleHttpParseResponse ?? HandleHttpParseResponse, TModel>( @@ -167,9 +167,9 @@ class DioExceptionHandler implements ClientExceptionHandler { /// {@macro DioExceptionHandler_callApi_} static Future> callApi_( - ApiHandler apiHandler, { - HandleHttpParseResponse? handleHttpParseResponse, - }) async => + final ApiHandler apiHandler, { + final HandleHttpParseResponse? handleHttpParseResponse, + }) => DioExceptionHandler().callApi( apiHandler, handleHttpParseResponse: handleHttpParseResponse, @@ -177,15 +177,16 @@ class DioExceptionHandler implements ClientExceptionHandler { /// _isConnected checks the current network connectivity status. static Future _isConnected() async { - final ConnectivityResult result = await connectivity.checkConnectivity(); + final List result = + await connectivity.checkConnectivity(); - return result != ConnectivityResult.none; + return !result.contains(ConnectivityResult.none); } /// _handleHttpResponse processes the HTTP response and handles different /// status codes. static Future> _handleHttpResponse( - ResponseParser, TModel> responseParser, + final ResponseParser, TModel> responseParser, ) async { final int? statusCode = responseParser.response.statusCode; @@ -193,8 +194,8 @@ class DioExceptionHandler implements ClientExceptionHandler { } static Future> _handleStatusCode( - int? statusCode, - ResponseParser, TModel> responseParser, + final int? statusCode, + final ResponseParser, TModel> responseParser, ) async => // coverage:ignore-start switch (statusCode) { @@ -233,8 +234,8 @@ class DioExceptionHandler implements ClientExceptionHandler { /// _handleDioException handles exceptions from the Dio library, /// particularly around connectivity. static Future> _handleDioException( - DioException e, - StackTrace s, + final DioException e, + final StackTrace s, ) async { const String start = 'This exception was thrown because the response has a status code of '; @@ -249,7 +250,7 @@ class DioExceptionHandler implements ClientExceptionHandler { ResponseParser( response: Response(requestOptions: RequestOptions()), // coverage:ignore-start - parserModel: (_) => Object() as TModel, + parserModel: (final _) => Object() as TModel, // coverage:ignore-end exception: e, stackTrace: s, diff --git a/lib/src/exception_handler/dio/dio_http_response_extension.dart b/lib/src/exception_handler/dio/dio_http_response_extension.dart index d891ed7..36b3040 100644 --- a/lib/src/exception_handler/dio/dio_http_response_extension.dart +++ b/lib/src/exception_handler/dio/dio_http_response_extension.dart @@ -8,7 +8,7 @@ import '../../../exception_handler.dart'; /// An extension on `Future` providing methods for handling Dio HTTP responses and converting them /// into [ResultState] or [ResultState>] types. -extension HttpResponseDioExtension on Future> { +extension DioHttpResponseExtension on Future> { /// Converts a Dio HTTP response into an [ResultState] type using /// a custom `fromJson` method. /// @@ -87,12 +87,13 @@ extension HttpResponseDioExtension on Future> { /// ``` /// Future> fromJson( - TModel Function(Map) fromJson, + final TModel Function(Map) fromJson, ) async => await DioExceptionHandler.callApi_, TModel>( ApiHandler( apiCall: () => this, // Same: response = dio.get('https://'). - parserModel: (Object? data) => fromJson(data as Map), + parserModel: (final Object? data) => + fromJson(data as Map), ), ); @@ -173,14 +174,13 @@ extension HttpResponseDioExtension on Future> { /// } /// ``` Future>> fromJsonAsList( - TModel Function(Map) fromJson, + final TModel Function(Map) fromJson, ) async => await DioExceptionHandler.callApi_, List>( ApiHandler( apiCall: () => this, // Same: response = dio.get('https://'). - parserModel: (Object? data) => (data as List>) - .map((item) => fromJson(item)) - .toList(), + parserModel: (final Object? data) => + (data as List>).map(fromJson).toList(), ), ); } diff --git a/lib/src/exception_state/exceptions_state.dart b/lib/src/exception_state/exception_state.dart similarity index 88% rename from lib/src/exception_state/exceptions_state.dart rename to lib/src/exception_state/exception_state.dart index da5304a..19aac1b 100644 --- a/lib/src/exception_state/exceptions_state.dart +++ b/lib/src/exception_state/exception_state.dart @@ -32,8 +32,8 @@ sealed class ExceptionState extends CustomEquatable /// the exception. class DataClientExceptionState extends ExceptionState { DataClientExceptionState({ - required String message, - required StackTrace stackTrace, + required final String message, + required final StackTrace stackTrace, }) : super(message: message, stackTrace: stackTrace) { log( 'Client exception captured:', @@ -44,7 +44,8 @@ class DataClientExceptionState extends ExceptionState { } @override - Map get namedProps => {'clientException': message}; + Map get namedProps => + {'clientException': message}; } /// [DataParseExceptionState] handles exceptions related to parsing issues @@ -55,8 +56,8 @@ class DataClientExceptionState extends ExceptionState { /// the exception. class DataParseExceptionState extends ExceptionState { DataParseExceptionState({ - required StackTrace stackTrace, - String message = 'Error parsing data.', + required final StackTrace stackTrace, + final String message = 'Error parsing data.', }) : super(message: message, stackTrace: stackTrace) { log( 'Unable to parse the json:', @@ -78,8 +79,8 @@ class DataParseExceptionState extends ExceptionState { class DataHttpExceptionState extends ExceptionState { DataHttpExceptionState({ required this.httpException, - required StackTrace stackTrace, - String? message, + required final StackTrace stackTrace, + final String? message, }) : super( message: message ?? '', stackTrace: stackTrace, @@ -107,8 +108,8 @@ class DataHttpExceptionState extends ExceptionState { /// the exception. class DataNetworkExceptionState extends ExceptionState { DataNetworkExceptionState({ - required StackTrace stackTrace, - String message = 'A network error occurred.', + required final StackTrace stackTrace, + final String message = 'A network error occurred.', }) : super(message: message, stackTrace: stackTrace) { log( 'Network exception captured:', @@ -130,8 +131,8 @@ class DataNetworkExceptionState extends ExceptionState { /// the exception. class DataCacheExceptionState extends ExceptionState { DataCacheExceptionState({ - required StackTrace stackTrace, - String message = 'A cache error occurred.', + required final StackTrace stackTrace, + final String message = 'A cache error occurred.', }) : super(message: message, stackTrace: stackTrace) { log( 'Cache exception captured:', @@ -153,8 +154,8 @@ class DataCacheExceptionState extends ExceptionState { /// the exception. class DataInvalidInputExceptionState extends ExceptionState { DataInvalidInputExceptionState({ - required StackTrace stackTrace, - String message = 'Invalid input provided.', + required final StackTrace stackTrace, + final String message = 'Invalid input provided.', }) : super(message: message, stackTrace: stackTrace) { log( 'Invalid Input exception captured:', @@ -176,8 +177,8 @@ class DataInvalidInputExceptionState extends ExceptionState { /// the exception. class DataUnknownExceptionState extends ExceptionState { DataUnknownExceptionState({ - required String message, - required StackTrace stackTrace, + required final String message, + required final StackTrace stackTrace, }) : super(message: message, stackTrace: stackTrace) { log( 'Unknown exception captured:', diff --git a/lib/src/result_state/result_state.dart b/lib/src/result_state/result_state.dart index 2cbb435..063a081 100644 --- a/lib/src/result_state/result_state.dart +++ b/lib/src/result_state/result_state.dart @@ -2,7 +2,7 @@ // All rights reserved. Use of this source code // is governed by a Apache-2.0 license that can be found in the LICENSE file. -import '../exception_state/exceptions_state.dart'; +import '../exception_state/exception_state.dart'; import '../utils/utils.dart'; /// An sealed base ResultState class diff --git a/lib/src/src.dart b/lib/src/src.dart index c1d990a..953fca3 100644 --- a/lib/src/src.dart +++ b/lib/src/src.dart @@ -2,7 +2,7 @@ // All rights reserved. Use of this source code // is governed by a Apache-2.0 license that can be found in the LICENSE file. -export 'exception_handler/exception_handler_client.dart'; -export 'exception_state/exceptions_state.dart'; +export 'exception_handler/client_exception_handler.dart'; +export 'exception_state/exception_state.dart'; export 'result_state/result_state.dart'; export 'utils/utils.dart'; diff --git a/lib/src/utils/custom_equatable.dart b/lib/src/utils/custom_equatable.dart index bdaae08..a7ccb30 100644 --- a/lib/src/utils/custom_equatable.dart +++ b/lib/src/utils/custom_equatable.dart @@ -4,7 +4,7 @@ import 'package:equatable/equatable.dart'; -import '../exception_state/exceptions_state.dart'; +import '../exception_state/exception_state.dart'; abstract class CustomEquatable extends Equatable { const CustomEquatable(); @@ -17,11 +17,11 @@ abstract class CustomEquatable extends Equatable { final String type = runtimeType.toString(); final String propList = namedProps.entries .map( - (MapEntry e) => (e.value is num || + (final MapEntry e) => (e.value is num || e.value is Exception || e.value is Enum || - e.value - is ExceptionState || // For internal exception handler. + // For internal exception handler. + e.value is ExceptionState || e.value == null) ? '${e.key}: ${e.value}' : e.value != null && e.value != '' diff --git a/lib/src/utils/isolates/_isolates_io.dart b/lib/src/utils/isolates/_isolates_io.dart index 9e5e306..5029627 100644 --- a/lib/src/utils/isolates/_isolates_io.dart +++ b/lib/src/utils/isolates/_isolates_io.dart @@ -15,8 +15,8 @@ export 'isolates.dart' show ComputeCallback; /// The dart:io implementation of [isolate.compute]. @pragma('vm:prefer-inline') Future compute( - isolates.ComputeCallback callback, - M message, { + final isolates.ComputeCallback callback, + final M message, { String? debugLabel, }) async { debugLabel ??= kReleaseMode ? 'compute' : callback.toString(); diff --git a/lib/src/utils/isolates/_isolates_web.dart b/lib/src/utils/isolates/_isolates_web.dart index 76ffbba..c137328 100644 --- a/lib/src/utils/isolates/_isolates_web.dart +++ b/lib/src/utils/isolates/_isolates_web.dart @@ -11,8 +11,8 @@ export 'isolates.dart' show ComputeCallback; /// The dart:html implementation of [isolate.compute]. @pragma('dart2js:tryInline') Future compute( - isolates.ComputeCallback callback, - M message, + final isolates.ComputeCallback callback, + final M message, ) async { // To avoid blocking the UI immediately for an expensive function call, we // pump a single frame to allow the framework to complete the current set diff --git a/lib/src/utils/isolates/isolates.dart b/lib/src/utils/isolates/isolates.dart index d24a9b9..50440c4 100644 --- a/lib/src/utils/isolates/isolates.dart +++ b/lib/src/utils/isolates/isolates.dart @@ -79,9 +79,9 @@ typedef ComputeImpl = Future Function( /// executes `callback`. [Timeline] events produced by that isolate will have /// the name associated with them. This is useful when profiling an application. Future compute( - ComputeCallback callback, - M message, { - String? debugLabel, + final ComputeCallback callback, + final M message, { + final String? debugLabel, }) { return isolates.compute(callback, message, debugLabel: debugLabel); } diff --git a/pubspec.lock b/pubspec.lock index adab59e..51a9a41 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -85,18 +85,18 @@ packages: dependency: "direct main" description: name: connectivity_plus - sha256: "224a77051d52a11fbad53dd57827594d3bd24f945af28bd70bab376d68d437f0" + sha256: e9feae83b1849f61bad9f6f33ee00646e3410d54ce0821e02f262f9901dad3c9 url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "6.0.1" connectivity_plus_platform_interface: dependency: transitive description: name: connectivity_plus_platform_interface - sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a + sha256: b6a56efe1e6675be240de39107281d4034b64ac23438026355b4234042a35adb url: "https://pub.dev" source: hosted - version: "1.2.4" + version: "2.0.0" convert: dependency: transitive description: @@ -150,10 +150,10 @@ packages: dependency: "direct main" description: name: dio - sha256: "49af28382aefc53562459104f64d16b9dfd1e8ef68c862d5af436cc8356ce5a8" + sha256: "50fec96118958b97c727d0d8f67255d3683f16cc1f90d9bc917b5d4fe3abeca9" url: "https://pub.dev" source: hosted - version: "5.4.1" + version: "5.4.2" equatable: dependency: "direct main" description: @@ -274,14 +274,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.3.0" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" json_annotation: dependency: transitive description: @@ -562,4 +554,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.3.0 <4.0.0" - flutter: ">=3.10.0" + flutter: ">=3.19.0" diff --git a/pubspec.yaml b/pubspec.yaml index 2f5276d..c904de6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,15 +1,15 @@ name: exception_handler description: A Dart package for streamlined API handling and robust exception management in Flutter apps. -version: 2.0.2 +version: 3.0.0 homepage: "https://github.com/andgar2010/exception_handler" environment: - sdk: '>=3.0.0 <4.0.0' - flutter: ">=3.10.0" + sdk: '>=3.3.0 <4.0.0' + flutter: ">=3.19.0" dependencies: - connectivity_plus: ^5.0.2 - dio: ^5.4.1 + connectivity_plus: ^6.0.1 + dio: ^5.4.2 equatable: ^2.0.5 http_exception: ^2.0.0 flutter: diff --git a/test/mocks.dart b/test/mocks.dart index 965d8f1..1552c24 100644 --- a/test/mocks.dart +++ b/test/mocks.dart @@ -26,7 +26,7 @@ class UserModel { this.website, }); - factory UserModel.fromJson(Map json) { + factory UserModel.fromJson(final Map json) { if (json case { 'id': final int? id, @@ -64,6 +64,7 @@ class UserModel { data['email'] = email; data['phone'] = phone; data['website'] = website; + return data; } } diff --git a/test/src/exception_handler/dio/dio_http_response_extension_test.dart b/test/src/exception_handler/dio/dio_http_response_extension_test.dart index 830090b..959daf7 100644 --- a/test/src/exception_handler/dio/dio_http_response_extension_test.dart +++ b/test/src/exception_handler/dio/dio_http_response_extension_test.dart @@ -14,7 +14,7 @@ class UserModel { required this.name, }); - factory UserModel.fromJson(Map json) => UserModel( + factory UserModel.fromJson(final Map json) => UserModel( id: json['id'] as int, name: json['name'] as String, ); @@ -27,7 +27,7 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); group('HttpResponseDioExtension', () { final requestOptions = - RequestOptions(path: '/data', validateStatus: (status) => true); + RequestOptions(path: '/data', validateStatus: (final status) => true); final data = {'id': 1, 'name': 'John Doe'}; @@ -37,8 +37,8 @@ void main() { ]; Future futureDioException( - DioExceptionType type, { - Response? response, + final DioExceptionType type, { + final Response? response, }) => Future.delayed( const Duration(microseconds: 10), @@ -55,7 +55,7 @@ void main() { mockConnectivity = MockConnectivity(); DioExceptionHandler.connectivity = mockConnectivity; when(() => mockConnectivity.checkConnectivity()) - .thenAnswer((_) async => ConnectivityResult.mobile); + .thenAnswer((final _) async => [ConnectivityResult.mobile]); }); group('fromJson', () { @@ -262,8 +262,9 @@ void main() { final dioResponse = futureDioException( DioExceptionType.badResponse, response: Response>( - requestOptions: - RequestOptions(validateStatus: (status) => status != null), + requestOptions: RequestOptions( + validateStatus: (final status) => status != null, + ), statusCode: null, ), ); @@ -302,8 +303,9 @@ void main() { final dioResponse = futureDioException( DioExceptionType.badResponse, response: Response>( - requestOptions: - RequestOptions(validateStatus: (status) => status != 100), + requestOptions: RequestOptions( + validateStatus: (final status) => status != 100, + ), statusCode: 100, ), ); @@ -336,8 +338,9 @@ void main() { final dioResponse = futureDioException( DioExceptionType.badResponse, response: Response>( - requestOptions: - RequestOptions(validateStatus: (status) => status != 300), + requestOptions: RequestOptions( + validateStatus: (final status) => status != 300, + ), statusCode: 300, ), ); @@ -369,8 +372,9 @@ void main() { final dioResponse = futureDioException( DioExceptionType.badResponse, response: Response>( - requestOptions: - RequestOptions(validateStatus: (status) => status != 400), + requestOptions: RequestOptions( + validateStatus: (final status) => status != 400, + ), statusCode: 400, ), ); @@ -403,8 +407,9 @@ void main() { final dioResponse = futureDioException( DioExceptionType.badResponse, response: Response>( - requestOptions: - RequestOptions(validateStatus: (status) => status != 500), + requestOptions: RequestOptions( + validateStatus: (final status) => status != 500, + ), statusCode: 500, ), ); @@ -642,8 +647,9 @@ void main() { final dioResponse = futureDioException( DioExceptionType.badResponse, response: Response>( - requestOptions: - RequestOptions(validateStatus: (status) => status != null), + requestOptions: RequestOptions( + validateStatus: (final status) => status != null, + ), statusCode: null, ), ); @@ -682,8 +688,9 @@ void main() { final dioResponse = futureDioException( DioExceptionType.badResponse, response: Response>( - requestOptions: - RequestOptions(validateStatus: (status) => status != 100), + requestOptions: RequestOptions( + validateStatus: (final status) => status != 100, + ), statusCode: 100, ), ); @@ -715,8 +722,9 @@ void main() { final dioResponse = futureDioException( DioExceptionType.badResponse, response: Response>( - requestOptions: - RequestOptions(validateStatus: (status) => status != 300), + requestOptions: RequestOptions( + validateStatus: (final status) => status != 300, + ), statusCode: 300, ), ); @@ -748,8 +756,9 @@ void main() { final dioResponse = futureDioException( DioExceptionType.badResponse, response: Response>( - requestOptions: - RequestOptions(validateStatus: (status) => status != 400), + requestOptions: RequestOptions( + validateStatus: (final status) => status != 400, + ), statusCode: 400, ), ); @@ -781,8 +790,9 @@ void main() { final dioResponse = futureDioException( DioExceptionType.badResponse, response: Response>( - requestOptions: - RequestOptions(validateStatus: (status) => status != 500), + requestOptions: RequestOptions( + validateStatus: (final status) => status != 500, + ), statusCode: 500, ), ); diff --git a/test/src/exception_handler/dio/exception_handler_dio_test.dart b/test/src/exception_handler/dio/exception_handler_dio_test.dart index 3410a47..7a3685b 100644 --- a/test/src/exception_handler/dio/exception_handler_dio_test.dart +++ b/test/src/exception_handler/dio/exception_handler_dio_test.dart @@ -29,7 +29,7 @@ void main() { 'Successful API call returns parsed data', () async { when(() => mockDio.get(any())).thenAnswer( - (_) async => Response( + (final _) async => Response( requestOptions: RequestOptions(path: ''), data: {'key': 'value'}, statusCode: 200, @@ -39,7 +39,8 @@ void main() { final ResultState result = await DioExceptionHandler.callApi_( ApiHandler( apiCall: () => mockDio.get('test'), - parserModel: (Object? data) => (data as Map)['key'] as String, + parserModel: (final Object? data) => + (data as Map)['key'] as String, ), ); @@ -61,7 +62,7 @@ void main() { 'API call with 401 status code returns unauthorized exception', () async { when(() => mockDio.get(any())).thenAnswer( - (_) async => Response( + (final _) async => Response( requestOptions: RequestOptions(path: ''), statusCode: 401, ), @@ -70,7 +71,7 @@ void main() { final result = await DioExceptionHandler.callApi_( ApiHandler( apiCall: () => mockDio.get('test'), - parserModel: (Object? data) => data as String, + parserModel: (final Object? data) => data as String, ), ); @@ -99,7 +100,7 @@ void main() { .thenThrow(DioException(requestOptions: RequestOptions())); when(() => mockConnectivity.checkConnectivity()) - .thenAnswer((_) async => ConnectivityResult.none); + .thenAnswer((final _) async => [ConnectivityResult.none]); final result = await DioExceptionHandler.callApi_(mockApiHandler); @@ -122,7 +123,7 @@ void main() { final result = await DioExceptionHandler.callApi_( ApiHandler( apiCall: () => mockDio.get('test'), - parserModel: (Object? data) => data as String, + parserModel: (final Object? data) => data as String, ), ); @@ -145,7 +146,7 @@ void main() { 'API call with parsing error', () async { when(() => mockDio.get(any())).thenAnswer( - (_) async => Response( + (final _) async => Response( requestOptions: RequestOptions(path: ''), data: 'Invalid data', statusCode: 200, @@ -155,7 +156,7 @@ void main() { final ResultState result = await DioExceptionHandler.callApi_( ApiHandler( apiCall: () => mockDio.get('test'), - parserModel: (Object? data) => int.parse(data as String) + parserModel: (final Object? data) => int.parse(data as String) .toString(), // Intentional parse error ), ); @@ -184,7 +185,7 @@ void main() { requestOptions: RequestOptions(path: ''), statusCode: 300, ), - parserModel: (res) => null, + parserModel: (final res) => null, ), ); @@ -206,7 +207,7 @@ void main() { 'should return FailureState with DataHttpException for 4xx error', () async { when(() => mockDio.get(any())).thenAnswer( - (_) async => Response( + (final _) async => Response( requestOptions: RequestOptions(path: ''), statusCode: 400, ), @@ -215,7 +216,7 @@ void main() { await DioExceptionHandler.callApi_( ApiHandler( apiCall: () => mockDio.get('test'), - parserModel: (res) => null, + parserModel: (final res) => null, ), ); @@ -239,7 +240,7 @@ void main() { 'should return FailureState with DataHttpException for 404 error', () async { when(() => mockDio.get(any())).thenAnswer( - (_) async => Response( + (final _) async => Response( requestOptions: RequestOptions(path: ''), statusCode: 404, ), @@ -248,7 +249,7 @@ void main() { await DioExceptionHandler.callApi_( ApiHandler( apiCall: () => mockDio.get('test'), - parserModel: (res) => null, + parserModel: (final res) => null, ), ); @@ -273,7 +274,7 @@ void main() { 'should return FailureState with DataHttpException for 500 error', () async { when(() => mockDio.get(any())).thenAnswer( - (_) async => Response( + (final _) async => Response( requestOptions: RequestOptions(path: ''), statusCode: 500, ), @@ -282,7 +283,7 @@ void main() { await DioExceptionHandler.callApi_( ApiHandler( apiCall: () => mockDio.get('test'), - parserModel: (res) => null, + parserModel: (final res) => null, ), ); expect(result, isA>()); @@ -305,7 +306,7 @@ void main() { 'should return FailureState with DataHttpException for 501 error', () async { when(() => mockDio.get(any())).thenAnswer( - (_) async => Response( + (final _) async => Response( requestOptions: RequestOptions(path: ''), statusCode: 501, ), @@ -314,7 +315,7 @@ void main() { await DioExceptionHandler.callApi_( ApiHandler( apiCall: () => mockDio.get('test'), - parserModel: (res) => null, + parserModel: (final res) => null, ), ); @@ -338,7 +339,7 @@ void main() { 'should return FailureState with DataHttpException for 600 error', () async { when(() => mockDio.get(any())).thenAnswer( - (_) async => Response( + (final _) async => Response( requestOptions: RequestOptions(path: ''), statusCode: 600, ), @@ -347,7 +348,7 @@ void main() { await DioExceptionHandler.callApi_( ApiHandler( apiCall: () => mockDio.get('test'), - parserModel: (res) => null, + parserModel: (final res) => null, ), ); @@ -386,7 +387,7 @@ void main() { ); when(() => mockConnectivity.checkConnectivity()) - .thenAnswer((_) async => ConnectivityResult.wifi); + .thenAnswer((final _) async => [ConnectivityResult.wifi]); final ResultState result = await DioExceptionHandler.callApi_(mockApiHandler); @@ -416,7 +417,7 @@ void main() { ); when(() => mockConnectivity.checkConnectivity()) - .thenAnswer((_) async => ConnectivityResult.wifi); + .thenAnswer((final _) async => [ConnectivityResult.wifi]); final ResultState result = await DioExceptionHandler.callApi_(mockApiHandler); @@ -446,7 +447,7 @@ void main() { ); when(() => mockConnectivity.checkConnectivity()) - .thenAnswer((_) async => ConnectivityResult.wifi); + .thenAnswer((final _) async => [ConnectivityResult.wifi]); final ResultState result = await DioExceptionHandler.callApi_(mockApiHandler); @@ -496,7 +497,7 @@ void main() { 'API call with unknown error', () async { when(() => mockDio.get(any())).thenAnswer( - (_) async => Response( + (final _) async => Response( requestOptions: RequestOptions(path: ''), data: 'Invalid data', statusCode: 200, @@ -506,7 +507,7 @@ void main() { final ResultState result = await DioExceptionHandler.callApi_( ApiHandler( apiCall: () => mockDio.get('test'), - parserModel: (Object? data) { + parserModel: (final Object? data) { throw Exception('Error Unknown'); // Intentional error }, ), diff --git a/test/src/exception_handler/typedef_test.dart b/test/src/exception_handler/typedef_test.dart index 3fe9cc3..6a0f7bf 100644 --- a/test/src/exception_handler/typedef_test.dart +++ b/test/src/exception_handler/typedef_test.dart @@ -14,7 +14,7 @@ void main() { statusCode: 200, requestOptions: RequestOptions(), ); - String mockParserModel(Object? data) => 'Parsed $data'; + String mockParserModel(final Object? data) => 'Parsed $data'; final handler = ApiHandler, String>( apiCall: mockApiCall, @@ -35,15 +35,18 @@ void main() { statusCode: 200, requestOptions: RequestOptions(), ); - String mockParserModel(Object? data) => (data as Map)['key'] as String; + String mockParserModel(final Object? data) => + (data as Map)['key'] as String; final parser = ResponseParser, String>( response: mockResponse, parserModel: mockParserModel, ); - test('should correctly parse the response using the given parserModel', - () { - expect(parser.parserModel(parser.response.data), equals('value')); - }); + test( + 'should correctly parse the response using the given parserModel', + () { + expect(parser.parserModel(parser.response.data), equals('value')); + }, + ); test( 'should correct toString', () {