diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml new file mode 100644 index 0000000..f04c014 --- /dev/null +++ b/.github/workflows/build_and_test.yml @@ -0,0 +1,35 @@ +name: Flutter Build And Test +on: + push: + branches: + - main + - unittest + pull_request: + branches: + - main +jobs: + build: + name: Analyze and Test + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Flutter + uses: subosito/flutter-action@v2.16.0 + with: + flutter-version: 3.24.4 + channel: stable + - name: Setup Dart + uses: dart-lang/setup-dart@v1.6.5 + with: + dart-version: 3.5.4 + - name: Install dependencies + run: flutter pub get + - name: Analyze + run: flutter analyze + - name: Run tests + run: flutter test +# - name: Build APK +# run: flutter build apk --release --target lib/main/main_prod.dart +# - name: Build Android App Bundle +# run: flutter build appbundle --release --target lib/main/main_prod.dart diff --git a/.gitignore b/.gitignore index d27d048..d2311cf 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,8 @@ migrate_working_dir/ *.iws .idea/ +.vscode/ + # The .vscode folder contains launch configuration and tasks you configure in # VS Code which you may wish to be included in version control, so this line # is commented out by default. diff --git a/android/app/build.gradle b/android/app/build.gradle index 07e2a8f..8b42842 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -23,9 +23,9 @@ if (flutterVersionName == null) { } android { - namespace "com.cevheri.flutter.flutter_bloc_advance" - compileSdkVersion 34 - ndkVersion flutter.ndkVersion + namespace = "com.cevheri.flutter.flutter_bloc_advance" + compileSdkVersion = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -33,7 +33,7 @@ android { } kotlinOptions { - jvmTarget = '1.8' + jvmTarget = JavaVersion.VERSION_1_8 } sourceSets { diff --git a/android/build.gradle b/android/build.gradle index 46ed8ed..20e69bd 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = "1.9.20" + ext.kotlin_version = "1.8.22" repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.3.0' + classpath 'com.android.tools.build:gradle:8.7.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 3c472b9..348c409 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/lib/data/models/user.dart b/lib/data/models/user.dart index ed68393..496a747 100644 --- a/lib/data/models/user.dart +++ b/lib/data/models/user.dart @@ -47,6 +47,7 @@ class User extends Equatable { // @JsonProperty(name: 'phoneNumber') // final String? phoneNumber; + //Constructor const User({ this.id, this.login, @@ -63,6 +64,7 @@ class User extends Equatable { // this.phoneNumber, }); + /// CopyWith method to create a new instance of the User class with new values User copyWith({ String? id, String? login, diff --git a/lib/main/initialize_reflectable.dart b/lib/main/initialize_reflectable.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/presentation/screen/register/bloc/register_bloc.dart b/lib/presentation/screen/register/bloc/register_bloc.dart index b5e79ab..ec1f2bd 100644 --- a/lib/presentation/screen/register/bloc/register_bloc.dart +++ b/lib/presentation/screen/register/bloc/register_bloc.dart @@ -26,7 +26,7 @@ class RegisterBloc extends Bloc { FutureOr _onSubmit(RegisterEmailChanged event, Emitter emit) async { emit(RegisterInitialState()); try { - var resultStatusCode = await _accountRepository.register(event.createUser); + await _accountRepository.register(event.createUser); emit(RegisterCompletedState()); } catch (e) { emit(const RegisterErrorState(message: "Register Error")); diff --git a/pubspec.lock b/pubspec.lock index 2fa67ed..29930f4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -94,6 +94,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.5" + bloc_test: + dependency: "direct dev" + description: + name: bloc_test + sha256: "165a6ec950d9252ebe36dc5335f2e6eb13055f33d56db0eeb7642768849b43d2" + url: "https://pub.dev" + source: hosted + version: "9.1.7" boolean_selector: dependency: transitive description: @@ -214,6 +222,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "88b0fddbe4c92910fefc09cc0248f5e7f0cd23e450ded4c28f16ab8ee8f83268" + url: "https://pub.dev" + source: hosted + version: "1.10.0" crypto: dependency: transitive description: @@ -270,6 +286,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + diff_match_patch: + dependency: transitive + description: + name: diff_match_patch + sha256: "2efc9e6e8f449d0abe15be240e2c2a3bcd977c8d126cfd70598aee60af35c0a4" + url: "https://pub.dev" + source: hosted + version: "0.4.1" dio: dependency: transitive description: @@ -674,6 +698,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + mockito: + dependency: "direct dev" + description: + name: mockito + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" + url: "https://pub.dev" + source: hosted + version: "5.4.4" + mocktail: + dependency: transitive + description: + name: mocktail + sha256: "890df3f9688106f25755f26b1c60589a92b3ab91a22b8b224947ad041bf172d8" + url: "https://pub.dev" + source: hosted + version: "1.0.4" modbus_client: dependency: transitive description: @@ -698,6 +738,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" package_config: dependency: transitive description: @@ -938,6 +986,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" shelf_web_socket: dependency: transitive description: @@ -951,6 +1015,30 @@ packages: description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" + source: hosted + version: "0.10.12" source_span: dependency: transitive description: @@ -1015,6 +1103,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + test: + dependency: "direct dev" + description: + name: test + sha256: "7ee44229615f8f642b68120165ae4c2a75fe77ae2065b1e55ae4711f6cf0899e" + url: "https://pub.dev" + source: hosted + version: "1.25.7" test_api: dependency: transitive description: @@ -1023,6 +1119,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.2" + test_core: + dependency: transitive + description: + name: test_core + sha256: "55ea5a652e38a1dfb32943a7973f3681a60f872f8c3a05a14664ad54ef9c6696" + url: "https://pub.dev" + source: hosted + version: "0.6.4" timing: dependency: transitive description: @@ -1087,6 +1191,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 903c0cd..f324726 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,6 +48,10 @@ dev_dependencies: sdk: flutter flutter_lints: ^5.0.0 build_runner: + test: ^1.25.7 + bloc_test: ^9.1.7 + mockito: ^5.4.4 + flutter_secure_storage: diff --git a/test/data/model/user_test.dart b/test/data/model/user_test.dart new file mode 100644 index 0000000..99a717d --- /dev/null +++ b/test/data/model/user_test.dart @@ -0,0 +1,138 @@ +import 'package:flutter_bloc_advance/data/models/user.dart'; +import 'package:flutter_bloc_advance/main/main_local.mapper.g.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + late User userModel; + // late String postUserJson; + // final mockDataPath = 'mock/'; + // final postUserMockData = 'POST_admin_users.json'; + // Initialize Test + setUp(() { + initializeJsonMapper(); + + userModel = User( + id: '1', + login: 'test_login', + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@example.com', + activated: true, + langKey: 'en', + createdBy: 'admin', + createdDate: DateTime(2021, 1, 1), + lastModifiedBy: 'admin', + lastModifiedDate: DateTime(2021, 1, 2), + authorities: ['ROLE_USER'], + ); + }); + + group('User Model', () { + test('should create a User instance (Constructor)', () { + final finalUser = userModel; + + expect(finalUser.id, '1'); + expect(finalUser.login, 'test_login'); + expect(finalUser.firstName, 'John'); + expect(finalUser.lastName, 'Doe'); + expect(finalUser.email, 'john.doe@example.com'); + expect(finalUser.activated, true); + expect(finalUser.langKey, 'en'); + expect(finalUser.createdBy, 'admin'); + expect(finalUser.createdDate, DateTime(2021, 1, 1)); + expect(finalUser.lastModifiedBy, 'admin'); + expect(finalUser.lastModifiedDate, DateTime(2021, 1, 2)); + expect(finalUser.authorities, ['ROLE_USER']); + }); + + test('should copy a User instance with new values (copyWith)', () { + final finalUser = userModel; + + final updatedUser = finalUser.copyWith( + firstName: 'Jane', + lastName: 'Smith', + ); + + expect(updatedUser.id, '1'); + expect(updatedUser.login, 'test_login'); + expect(updatedUser.firstName, 'Jane'); + expect(updatedUser.lastName, 'Smith'); + expect(updatedUser.email, 'john.doe@example.com'); + expect(updatedUser.activated, true); + expect(updatedUser.langKey, 'en'); + expect(updatedUser.createdBy, 'admin'); + expect(updatedUser.createdDate, DateTime(2021, 1, 1)); + expect(updatedUser.lastModifiedBy, 'admin'); + expect(updatedUser.lastModifiedDate, DateTime(2021, 1, 2)); + expect(updatedUser.authorities, ['ROLE_USER']); + }); + + test('should deserialize from JSON', () { + const json = { + 'id': '1', + 'login': 'test_login', + 'firstName': 'John', + 'lastName': 'Doe', + 'email': 'john.doe@example.com', + 'activated': true, + 'langKey': 'en', + 'createdBy': 'admin', + 'createdDate': '2021-01-01T00:00:00.000Z', + 'lastModifiedBy': 'admin', + 'lastModifiedDate': '2021-01-02T00:00:00.000Z', + 'authorities': ['ROLE_USER'], + }; + + final finalUser = User.fromJson(json); + + expect(finalUser?.id, '1'); + expect(finalUser?.login, 'test_login'); + expect(finalUser?.firstName, 'John'); + expect(finalUser?.lastName, 'Doe'); + expect(finalUser?.email, 'john.doe@example.com'); + expect(finalUser?.activated, true); + expect(finalUser?.langKey, 'en'); + expect(finalUser?.createdBy, 'admin'); + expect(finalUser?.createdDate, DateTime.parse('2021-01-01T00:00:00.000Z')); + expect(finalUser?.lastModifiedBy, 'admin'); + expect(finalUser?.lastModifiedDate, DateTime.parse('2021-01-02T00:00:00.000Z')); + expect(finalUser?.authorities, ['ROLE_USER']); + }); + + test('should deserialize from JSON string', () { + //postUserJson = await rootBundle.loadString(mockDataPath+postUserMockData); + + const jsonString = ''' + { + "id": "1", + "login": "test_login", + "firstName": "John", + "lastName": "Doe", + "email": "john.doe@example.com", + "activated": true, + "langKey": "en", + "createdBy": "admin", + "createdDate": "2021-01-01T00:00:00.000Z", + "lastModifiedBy": "admin", + "lastModifiedDate": "2021-01-02T00:00:00.000Z", + "authorities": ["ROLE_USER"] + } + '''; + + final finalUser = User.fromJsonString(jsonString); + + expect(finalUser?.id, '1'); + expect(finalUser?.login, 'test_login'); + expect(finalUser?.firstName, 'John'); + expect(finalUser?.lastName, 'Doe'); + expect(finalUser?.email, 'john.doe@example.com'); + expect(finalUser?.activated, true); + expect(finalUser?.langKey, 'en'); + expect(finalUser?.createdBy, 'admin'); + expect(finalUser?.createdDate, DateTime.parse('2021-01-01T00:00:00.000Z')); + expect(finalUser?.lastModifiedBy, 'admin'); + expect(finalUser?.lastModifiedDate, DateTime.parse('2021-01-02T00:00:00.000Z')); + expect(finalUser?.authorities, ['ROLE_USER']); + }); + }); +} diff --git a/test/data/repository/package_info.dart b/test/data/repository/package_info.dart new file mode 100644 index 0000000..e69de29 diff --git a/test/main_local.dart b/test/main_local.dart new file mode 100644 index 0000000..d088afd --- /dev/null +++ b/test/main_local.dart @@ -0,0 +1,5 @@ +import 'package:flutter_bloc_advance/main/main_local.mapper.g.dart'; + +void init(){ + initializeJsonMapper(); +} \ No newline at end of file diff --git a/test/main_prod.dart b/test/main_prod.dart new file mode 100644 index 0000000..24340fc --- /dev/null +++ b/test/main_prod.dart @@ -0,0 +1,5 @@ +import 'package:flutter_bloc_advance/main/main_prod.mapper.g.dart'; + +void main(){ + initializeJsonMapper(); +} \ No newline at end of file diff --git a/test/presentation/blocs/package_info.dart b/test/presentation/blocs/package_info.dart new file mode 100644 index 0000000..e69de29 diff --git a/test/presentation/screen/user/package_info.dart b/test/presentation/screen/user/package_info.dart new file mode 100644 index 0000000..e69de29 diff --git a/test/presentation/widgets/package_info.dart b/test/presentation/widgets/package_info.dart new file mode 100644 index 0000000..e69de29