diff --git a/.cicdtemplate/.codemagic/README.md b/.cicdtemplate/.codemagic/README.md new file mode 100644 index 000000000..85f292026 --- /dev/null +++ b/.cicdtemplate/.codemagic/README.md @@ -0,0 +1,34 @@ +# Setup + +Setting up the [Codemagic](https://codemagic.io/start/) to the project starts from adding project to +the Codemagic console. +After that, you can follow the instruction below to setup the environment variables and deployment. + +# Environment Variables + +You can configure the environment variables for Codemagic by accessing the `Environment Variables` +tab under `App Settings`. +For detailed instructions on how to configure these variables, please refer +to [this document](https://docs.codemagic.io/yaml-basic-configuration/configuring-environment-variables/#configuring-environment-variables) +. + +# Deploy to Firebase App Distribution (FAD) + +1. Set up the Firebase SDK in your app by following + the [Get started guide for Android](https://firebase.google.com/docs/android/setup). +2. Create service account for Codemagic by following + the [Firebase App Distribution with codemagic.yaml](https://docs.codemagic.io/yaml-publishing/firebase-app-distribution/) + at `Authenticating via service account` which is recommended. +3. Update the script on `app_id` and tester `groups` in `codemagic.yaml` file: + + ```yaml + publishing: + firebase: + firebase_service_account: $FIREBASE_SERVICE_ACCOUNT + android: + app_id: x:xxxxxxxxxxxx:android:xxxxxxxxxxxxxxxxxxxxxx + groups: + - androidTesters + - ... + artifact_type: 'apk' # Replace with 'aab' to only publish the Android app bundle + ``` diff --git a/.cicdtemplate/.codemagic/codemagic.yaml b/.cicdtemplate/.codemagic/codemagic.yaml new file mode 100644 index 000000000..97392cd19 --- /dev/null +++ b/.cicdtemplate/.codemagic/codemagic.yaml @@ -0,0 +1,108 @@ +definitions: + configure_environment: &configure_environment + # This running machine can be changed depends on the billing plan: https://docs.codemagic.io/knowledge-codemagic/machine-type/ + instance_type: mac_mini_m1 + max_build_duration: 30 + environment: + groups: + - firebase_credentials + cache: + cache_paths: + - $HOME/.gradle/caches + scripts: + - &set_up_google_services_files_from_environment_variables + name: Set up google-services.json files + script: | + mkdir -p app/src/production + echo $GOOGLE_SERVICES_JSON > app/src/production/google-services.json + mkdir -p app/src/staging + echo $GOOGLE_SERVICES_JSON_STAGING > app/src/staging/google-services.json + - &detekt + name: Run detekt + script: ./gradlew detekt + - &unit_test + name: Run unit tests + script: ./gradlew koverMergedReport + artifacts: + - &artifacts_test_report build/reports/kover/merged/ + - &artifacts_staging_apk app/build/outputs/apk/staging/debug/app-staging-debug.apk + - &artifacts_production_apk app/build/outputs/apk/production/debug/app-production-debug.apk +workflows: + unit-test-on-pr: + name: Unit test on PR + <<: *configure_environment + triggering: + events: + # Run when a pull request is opened or updated + - pull_request + branch_patterns: + # Review changes BEFORE they’re merged into any branches + - pattern: '*' + source: false + # Will not run on develop branch as it is already covered by build-and-deploy-template-compose-staging + - pattern: 'develop' + include: false + # Will not run on main branch as it is already covered by build-and-deploy-template-compose-production + - pattern: 'main' + include: false + cancel_previous_builds: true + scripts: + - *set_up_google_services_files_from_environment_variables + - *detekt + - *unit_test + artifacts: + - *artifacts_test_report + + build-and-deploy-staging: + name: Build and deploy staging to Firebase App Distribution + <<: *configure_environment + triggering: + events: + - push + branch_patterns: + - pattern: develop + scripts: + - *set_up_google_services_files_from_environment_variables + - *detekt + - *unit_test + - name: Build APK for staging + script: | + ./gradlew assembleStagingDebug -PversionCode=$BUILD_NUMBER + artifacts: + - *artifacts_test_report + - *artifacts_staging_apk + publishing: + firebase: + firebase_service_account: $FIREBASE_SERVICE_ACCOUNT_CREDENTIALS + android: + app_id: $FIREBASE_APP_ID_STAGING + groups: + - android-chapter + artifact_type: 'apk' + + build-and-deploy-production: + name: Build and deploy production to Firebase App Distribution + <<: *configure_environment + triggering: + events: + - push + branch_patterns: + - pattern: main + scripts: + - *set_up_google_services_files_from_environment_variables + - *detekt + - *unit_test + - name: Build APK for production + script: | + ./gradlew assembleProductionDebug -PversionCode=$BUILD_NUMBER + artifacts: + - *artifacts_test_report + - *artifacts_production_apk + publishing: + firebase: + firebase_service_account: $FIREBASE_SERVICE_ACCOUNT_CREDENTIALS + android: + app_id: $FIREBASE_APP_ID_PRODUCTION + groups: + - android-chapter + artifact_type: 'apk' diff --git a/.cicdtemplate/.github/workflows/deploy_staging_and_production_to_firebase_app_distribution.yml b/.cicdtemplate/.github/workflows/deploy_staging_and_production_to_firebase_app_distribution.yml index f684c2826..e9f176882 100644 --- a/.cicdtemplate/.github/workflows/deploy_staging_and_production_to_firebase_app_distribution.yml +++ b/.cicdtemplate/.github/workflows/deploy_staging_and_production_to_firebase_app_distribution.yml @@ -38,6 +38,16 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- + - name: Set up google-services.json files + env: + GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} + GOOGLE_SERVICES_JSON_STAGING: ${{ secrets.GOOGLE_SERVICES_JSON_STAGING }} + run: | + mkdir -p app/src/production + echo $GOOGLE_SERVICES_JSON > app/src/production/google-services.json + mkdir -p app/src/staging + echo $GOOGLE_SERVICES_JSON_STAGING > app/src/staging/google-services.json + - name: Run Detekt run: ./gradlew detekt diff --git a/.cicdtemplate/.github/workflows/review_pull_request.yml b/.cicdtemplate/.github/workflows/review_pull_request.yml index 699cb6439..b68386562 100644 --- a/.cicdtemplate/.github/workflows/review_pull_request.yml +++ b/.cicdtemplate/.github/workflows/review_pull_request.yml @@ -30,6 +30,16 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- + - name: Set up google-services.json + env: + GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} + GOOGLE_SERVICES_JSON_STAGING: ${{ secrets.GOOGLE_SERVICES_JSON_STAGING }} + run: | + mkdir -p app/src/production + echo $GOOGLE_SERVICES_JSON > app/src/production/google-services.json + mkdir -p app/src/staging + echo $GOOGLE_SERVICES_JSON_STAGING > app/src/staging/google-services.json + - name: Run Detekt run: ./gradlew detekt diff --git a/.cicdtemplate/.github/workflows/run_detekt_and_unit_tests.yml b/.cicdtemplate/.github/workflows/run_detekt_and_unit_tests.yml index 2a045f20b..2fabaf2d8 100644 --- a/.cicdtemplate/.github/workflows/run_detekt_and_unit_tests.yml +++ b/.cicdtemplate/.github/workflows/run_detekt_and_unit_tests.yml @@ -41,6 +41,13 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- + - name: Set up google-services.json + env: + GOOGLE_SERVICES_JSON_STAGING: ${{ secrets.GOOGLE_SERVICES_JSON_STAGING }} + run: | + mkdir -p app/src/staging + echo $GOOGLE_SERVICES_JSON_STAGING > app/src/staging/google-services.json + - name: Run Detekt run: ./gradlew detekt diff --git a/.github/workflows/review_pull_request.yml b/.github/workflows/review_pull_request.yml index 68ad53257..1b5f61fe3 100644 --- a/.github/workflows/review_pull_request.yml +++ b/.github/workflows/review_pull_request.yml @@ -9,6 +9,7 @@ jobs: name: Review pull request runs-on: ubuntu-latest timeout-minutes: 30 + environment: template-compose steps: - name: Set up JDK 11 uses: actions/setup-java@v2 @@ -46,6 +47,16 @@ jobs: # template-compose + - name: Set up google-services.json on template-compose + env: + GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} + GOOGLE_SERVICES_JSON_STAGING: ${{ secrets.GOOGLE_SERVICES_JSON_STAGING }} + run: | + mkdir -p template-compose/app/src/production + echo $GOOGLE_SERVICES_JSON > template-compose/app/src/production/google-services.json + mkdir -p template-compose/app/src/staging + echo $GOOGLE_SERVICES_JSON_STAGING > template-compose/app/src/staging/google-services.json + - name: Run Detekt on template-compose working-directory: ./template-compose run: ./gradlew detekt diff --git a/.github/workflows/run_detekt_and_unit_tests.yml b/.github/workflows/run_detekt_and_unit_tests.yml index 9e40a351e..bc483489f 100644 --- a/.github/workflows/run_detekt_and_unit_tests.yml +++ b/.github/workflows/run_detekt_and_unit_tests.yml @@ -7,6 +7,7 @@ jobs: name: Run Detekt and unit tests runs-on: ubuntu-latest timeout-minutes: 30 + environment: template-compose steps: - name: Set up JDK 11 uses: actions/setup-java@v2 @@ -52,6 +53,13 @@ jobs: # template-compose + - name: Set up google-services.json on template-compose + env: + GOOGLE_SERVICES_JSON_STAGING: ${{ secrets.GOOGLE_SERVICES_JSON_STAGING }} + run: | + mkdir -p template-compose/app/src/staging + echo $GOOGLE_SERVICES_JSON_STAGING > template-compose/app/src/staging/google-services.json + - name: Run Detekt on template-compose working-directory: ./template-compose run: ./gradlew detekt diff --git a/README.md b/README.md index 40a882607..7344a78a1 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ --- A collection of our Android templates: + - XML template: **[template-xml](https://github.com/nimblehq/android-templates/tree/develop/template-xml)** - Compose template: **[template-compose](https://github.com/nimblehq/android-templates/tree/develop/template-compose)** @@ -23,6 +24,7 @@ A collection of our Android templates: 1. Clone or download this repository to your local machine, then extract and open the folder 2. Run `cd scripts` to get into the scripts directory 3. Run `kscript new_project.kts` to create a new project with the following arguments: + ``` package-name= New package name (i.e., com.example.package) app-name= New app name (i.e., MyApp, "My App", "my-app") @@ -31,10 +33,19 @@ A collection of our Android templates: destination= Set the output location where the project should be generated (i.e., /Users/johndoe/documents/projectfolder) ``` - Examples: - `kscript new_project.kts package-name=co.myxmlproject.example app-name="My XML Project" template=xml` - `kscript scripts/new_project.kts package-name=co.myxmlproject.example app-name="My XML Project" template=xml` - `kscript new_project.kts package-name=co.myxmlproject.example app-name="My XML Project" template=xml destination=/Users/johndoe/documents/projectfolder` +Examples: + +``` + kscript new_project.kts package-name=co.myxmlproject.example app-name="My XML Project" template=xml +``` + +``` + kscript scripts/new_project.kts package-name=co.myxmlproject.example app-name="My XML Project" template=xml +``` + +``` + kscript new_project.kts package-name=co.myxmlproject.example app-name="My XML Project" template=xml destination=/Users/johndoe/documents/projectfolder +``` 4. Update `android_version_code` and `android_version_name` in `template/build.gradle` @@ -49,6 +60,7 @@ This project is Copyright (c) 2014 and onwards Nimble. It is free software and m [LICENSE]: /LICENSE ## About + diff --git a/RxJavaTemplate[DEPRECATED]/build.gradle.kts b/RxJavaTemplate[DEPRECATED]/build.gradle.kts index e34ef57ce..caef53a22 100644 --- a/RxJavaTemplate[DEPRECATED]/build.gradle.kts +++ b/RxJavaTemplate[DEPRECATED]/build.gradle.kts @@ -21,8 +21,8 @@ plugins { allprojects { repositories { google() - maven(url = "https://jitpack.io") mavenCentral() + maven { url = uri("https://www.jitpack.io") } } } diff --git a/codemagic.yaml b/codemagic.yaml new file mode 100644 index 000000000..845d9e33d --- /dev/null +++ b/codemagic.yaml @@ -0,0 +1,145 @@ +definitions: + configure_environment: &configure_environment + # This running machine can be changed depends on the billing plan: https://docs.codemagic.io/knowledge-codemagic/machine-type/ + instance_type: mac_mini_m1 + max_build_duration: 30 + environment: + groups: + - firebase_credentials + cache: + cache_paths: + - $HOME/.gradle/caches + scripts: + - &set_up_google_services_files_from_environment_variables + name: Set up google-services.json on template-compose + script: | + mkdir -p template-compose/app/src/production + echo $GOOGLE_SERVICES_JSON > template-compose/app/src/production/google-services.json + mkdir -p template-compose/app/src/staging + echo $GOOGLE_SERVICES_JSON_STAGING > template-compose/app/src/staging/google-services.json + - &detekt_on_template_compose + name: Run detekt on template-compose + working_directory: ./template-compose + script: ./gradlew detekt + - &detekt_on_template_xml + name: Run detekt on template-xml + working_directory: ./template-xml + script: ./gradlew detekt + - &unit_test_on_template_compose + name: Run unit tests on template-compose + working_directory: ./template-compose + script: ./gradlew koverMergedReport + - &unit_test_on_template_xml + name: Run unit tests on template-xml + working_directory: ./template-xml + script: ./gradlew koverMergedReport + artifacts: + - &artifacts_template_compose template-compose/build/reports/kover/merged/ + - &artifacts_template_xml template-xml/build/reports/kover/merged/ + - &artifacts_staging_apk template-compose/app/build/outputs/apk/staging/debug/app-staging-debug.apk + - &artifacts_production_apk template-compose/app/build/outputs/apk/production/debug/app-production-debug.apk +workflows: + unit-test-on-pr-for-template-compose: + name: Unit test on PR for template-compose + <<: *configure_environment + triggering: + events: + # Run when a pull request is opened or updated + - pull_request + branch_patterns: + # Review changes BEFORE they’re merged into any branches + - pattern: '*' + source: false + # Will not run on develop branch as it is already covered by build-and-deploy-template-compose-staging + - pattern: 'develop' + include: false + # Will not run on main branch as it is already covered by build-and-deploy-template-compose-production + - pattern: 'main' + include: false + cancel_previous_builds: true + scripts: + - *set_up_google_services_files_from_environment_variables + - *detekt_on_template_compose + - *unit_test_on_template_compose + artifacts: + - *artifacts_template_compose + + unit-test-on-pr-for-template-xml: + name: Unit test on PR for template-xml + <<: *configure_environment + triggering: + events: + # Run when a pull request is opened or updated + - pull_request + branch_patterns: + # Review changes BEFORE they’re merged into any branches + - pattern: '*' + source: false + # Will not run on develop branch as it is already covered by build-and-deploy-template-compose-staging + - pattern: 'develop' + include: false + # Will not run on main branch as it is already covered by build-and-deploy-template-compose-production + - pattern: 'main' + include: false + cancel_previous_builds: true + scripts: + - *detekt_on_template_xml + - *unit_test_on_template_xml + artifacts: + - *artifacts_template_xml + + build-and-deploy-template-compose-staging: + name: Build and deploy template-compose staging to Firebase App Distribution + <<: *configure_environment + triggering: + events: + - push + branch_patterns: + - pattern: develop + scripts: + - *set_up_google_services_files_from_environment_variables + - *detekt_on_template_compose + - *unit_test_on_template_compose + - name: Build APK for staging + working_directory: ./template-compose + script: | + ./gradlew assembleStagingDebug -PversionCode=$BUILD_NUMBER + artifacts: + - *artifacts_template_compose + - *artifacts_staging_apk + publishing: + firebase: + firebase_service_account: $FIREBASE_SERVICE_ACCOUNT_CREDENTIALS + android: + app_id: $FIREBASE_APP_ID_STAGING + groups: + - android-chapter + artifact_type: 'apk' + + build-and-deploy-template-compose-production: + name: Build and deploy template-compose production to Firebase App Distribution + <<: *configure_environment + triggering: + events: + - push + branch_patterns: + - pattern: main + scripts: + - *set_up_google_services_files_from_environment_variables + - *detekt_on_template_compose + - *unit_test_on_template_compose + - name: Build APK for production + working_directory: ./template-compose + script: | + ./gradlew assembleProductionDebug -PversionCode=$BUILD_NUMBER + artifacts: + - *artifacts_template_compose + - *artifacts_production_apk + publishing: + firebase: + firebase_service_account: $FIREBASE_SERVICE_ACCOUNT_CREDENTIALS + android: + app_id: $FIREBASE_APP_ID_PRODUCTION + groups: + - android-chapter + artifact_type: 'apk' diff --git a/sample-compose/app/proguard-rules.pro b/sample-compose/app/proguard-rules.pro index 2f9dc5a47..3183d4753 100644 --- a/sample-compose/app/proguard-rules.pro +++ b/sample-compose/app/proguard-rules.pro @@ -19,3 +19,7 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile + +# Data class +-keepclassmembers class co.nimblehq.sample.compose.data.request.** { *; } +-keepclassmembers class co.nimblehq.sample.compose.data.response.** { *; } diff --git a/sample-compose/app/src/debug/AndroidManifest.xml b/sample-compose/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..9d1fb7585 --- /dev/null +++ b/sample-compose/app/src/debug/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/sample-compose/app/src/main/java/co/nimblehq/sample/compose/model/UiModel.kt b/sample-compose/app/src/main/java/co/nimblehq/sample/compose/model/UiModel.kt index f8df0dd51..63d7184cb 100644 --- a/sample-compose/app/src/main/java/co/nimblehq/sample/compose/model/UiModel.kt +++ b/sample-compose/app/src/main/java/co/nimblehq/sample/compose/model/UiModel.kt @@ -6,7 +6,11 @@ import kotlinx.parcelize.Parcelize @Parcelize data class UiModel( - val id: String + val id: String, + val username: String, ) : Parcelable -fun Model.toUiModel() = UiModel(id.toString()) +fun Model.toUiModel() = UiModel( + id.toString(), + username.orEmpty(), +) diff --git a/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/HomeScreen.kt b/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/HomeScreen.kt index b2b521d73..47fd782fa 100644 --- a/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/HomeScreen.kt +++ b/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/HomeScreen.kt @@ -109,7 +109,7 @@ private fun HomeScreenContent( private fun HomeScreenPreview() { ComposeTheme { HomeScreenContent( - uiModels = listOf(UiModel("1"), UiModel("2"), UiModel("3")), + uiModels = listOf(UiModel("1", "name1"), UiModel("2", "name2"), UiModel("3", "name3")), isLoading = false, onItemClick = {}, onItemLongClick = {} diff --git a/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/Item.kt b/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/Item.kt index 91fabd676..26e589aeb 100644 --- a/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/Item.kt +++ b/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/Item.kt @@ -30,12 +30,21 @@ fun Item( onLongClick = { expanded = true } ) ) { - Text( - modifier = Modifier - .padding(dimensions.spacingNormal) - .fillMaxWidth(0.8f), - text = uiModel.id - ) + Row { + Text( + modifier = Modifier + .padding(dimensions.spacingNormal) + .weight(1f), + text = uiModel.id + ) + Text( + modifier = Modifier + .padding(dimensions.spacingNormal) + .weight(2f), + text = uiModel.username + ) + } + DropdownMenu( expanded = expanded, onDismissRequest = { expanded = false } @@ -52,7 +61,7 @@ fun Item( private fun ItemPreview() { ComposeTheme { Item( - uiModel = UiModel("1"), + uiModel = UiModel("1", "name1"), onClick = {}, onLongClick = {} ) diff --git a/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/ItemList.kt b/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/ItemList.kt index 2323ecee9..0ccf1bdff 100644 --- a/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/ItemList.kt +++ b/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/home/ItemList.kt @@ -33,7 +33,7 @@ fun ItemList( private fun ItemListPreview() { ComposeTheme { ItemList( - uiModels = listOf(UiModel("1"), UiModel("2"), UiModel("3")), + uiModels = listOf(UiModel("1", "name1"), UiModel("2", "name2"), UiModel("3", "name3")), onItemClick = {}, onItemLongClick = {} ) diff --git a/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/third/ThirdScreen.kt b/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/third/ThirdScreen.kt index 458c53d23..f7905ac4d 100644 --- a/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/third/ThirdScreen.kt +++ b/sample-compose/app/src/main/java/co/nimblehq/sample/compose/ui/screens/third/ThirdScreen.kt @@ -1,6 +1,8 @@ package co.nimblehq.sample.compose.ui.screens.third -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.material.Scaffold import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -20,7 +22,7 @@ import co.nimblehq.sample.compose.ui.theme.ComposeTheme fun ThirdScreen( viewModel: ThirdViewModel = hiltViewModel(), navigator: (destination: AppDestination) -> Unit, - model: UiModel? + model: UiModel?, ) { ThirdScreenContent(data = model) } @@ -50,6 +52,6 @@ fun ThirdScreenContent(data: UiModel?) { @Composable fun ThirdScreenPreview() { ComposeTheme { - ThirdScreenContent(data = UiModel("1")) + ThirdScreenContent(data = UiModel("1", "name1")) } } diff --git a/sample-compose/app/src/test/java/co/nimblehq/sample/compose/test/MockUtil.kt b/sample-compose/app/src/test/java/co/nimblehq/sample/compose/test/MockUtil.kt new file mode 100644 index 000000000..d79a92a4c --- /dev/null +++ b/sample-compose/app/src/test/java/co/nimblehq/sample/compose/test/MockUtil.kt @@ -0,0 +1,21 @@ +package co.nimblehq.sample.compose.test + +import co.nimblehq.sample.compose.domain.model.Model + +object MockUtil { + + val models = listOf( + Model( + id = 1, + username = "name1", + ), + Model( + id = 2, + username = "name2", + ), + Model( + id = 3, + username = "name3", + ), + ) +} diff --git a/sample-compose/app/src/test/java/co/nimblehq/sample/compose/ui/screens/home/HomeScreenTest.kt b/sample-compose/app/src/test/java/co/nimblehq/sample/compose/ui/screens/home/HomeScreenTest.kt index cb67695aa..5981e4946 100644 --- a/sample-compose/app/src/test/java/co/nimblehq/sample/compose/ui/screens/home/HomeScreenTest.kt +++ b/sample-compose/app/src/test/java/co/nimblehq/sample/compose/ui/screens/home/HomeScreenTest.kt @@ -7,8 +7,8 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.rule.GrantPermissionRule import co.nimblehq.sample.compose.R -import co.nimblehq.sample.compose.domain.model.Model import co.nimblehq.sample.compose.domain.usecase.* +import co.nimblehq.sample.compose.test.MockUtil import co.nimblehq.sample.compose.ui.AppDestination import co.nimblehq.sample.compose.ui.screens.BaseScreenTest import co.nimblehq.sample.compose.ui.screens.MainActivity @@ -49,9 +49,7 @@ class HomeScreenTest : BaseScreenTest() { @Before fun setUp() { - every { mockGetModelsUseCase() } returns flowOf( - listOf(Model(1), Model(2), Model(3)) - ) + every { mockGetModelsUseCase() } returns flowOf(MockUtil.models) every { mockIsFirstTimeLaunchPreferencesUseCase() } returns flowOf(false) coEvery { mockUpdateFirstTimeLaunchPreferencesUseCase(any()) } just Runs } diff --git a/sample-compose/app/src/test/java/co/nimblehq/sample/compose/ui/screens/home/HomeViewModelTest.kt b/sample-compose/app/src/test/java/co/nimblehq/sample/compose/ui/screens/home/HomeViewModelTest.kt index 91cea39b6..e5bb7dcc2 100644 --- a/sample-compose/app/src/test/java/co/nimblehq/sample/compose/ui/screens/home/HomeViewModelTest.kt +++ b/sample-compose/app/src/test/java/co/nimblehq/sample/compose/ui/screens/home/HomeViewModelTest.kt @@ -1,18 +1,24 @@ package co.nimblehq.sample.compose.ui.screens.home import app.cash.turbine.test -import co.nimblehq.sample.compose.domain.model.Model -import co.nimblehq.sample.compose.domain.usecase.* +import co.nimblehq.sample.compose.domain.usecase.GetModelsUseCase +import co.nimblehq.sample.compose.domain.usecase.IsFirstTimeLaunchPreferencesUseCase +import co.nimblehq.sample.compose.domain.usecase.UpdateFirstTimeLaunchPreferencesUseCase import co.nimblehq.sample.compose.model.toUiModel import co.nimblehq.sample.compose.test.CoroutineTestRule +import co.nimblehq.sample.compose.test.MockUtil import co.nimblehq.sample.compose.ui.AppDestination import co.nimblehq.sample.compose.util.DispatchersProvider import io.kotest.matchers.shouldBe import io.mockk.* import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.* -import kotlinx.coroutines.test.* -import org.junit.* +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Rule +import org.junit.Test @ExperimentalCoroutinesApi class HomeViewModelTest { @@ -26,12 +32,11 @@ class HomeViewModelTest { private lateinit var viewModel: HomeViewModel - private val models = listOf(Model(1), Model(2), Model(3)) private val isFirstTimeLaunch = false @Before fun setUp() { - every { mockGetModelsUseCase() } returns flowOf(models) + every { mockGetModelsUseCase() } returns flowOf(MockUtil.models) every { mockIsFirstTimeLaunchPreferencesUseCase() } returns flowOf(isFirstTimeLaunch) coEvery { mockUpdateFirstTimeLaunchPreferencesUseCase(any()) } just Runs @@ -41,7 +46,7 @@ class HomeViewModelTest { @Test fun `When loading models successfully, it shows the model list`() = runTest { viewModel.uiModels.test { - expectMostRecentItem() shouldBe models.map { it.toUiModel() } + expectMostRecentItem() shouldBe MockUtil.models.map { it.toUiModel() } } } @@ -72,7 +77,7 @@ class HomeViewModelTest { @Test fun `When calling navigate to Second, it navigates to Second screen`() = runTest { viewModel.navigator.test { - viewModel.navigateToSecond(models[0].toUiModel()) + viewModel.navigateToSecond(MockUtil.models[0].toUiModel()) expectMostRecentItem() shouldBe AppDestination.Second } diff --git a/sample-compose/build.gradle.kts b/sample-compose/build.gradle.kts index 267fe3af3..7a63ad82a 100644 --- a/sample-compose/build.gradle.kts +++ b/sample-compose/build.gradle.kts @@ -20,8 +20,8 @@ plugins { allprojects { repositories { google() - maven(url = "https://jitpack.io") mavenCentral() + maven { url = uri("https://www.jitpack.io") } } } diff --git a/sample-compose/buildSrc/src/main/java/Versions.kt b/sample-compose/buildSrc/src/main/java/Versions.kt index f8c2444c3..74036ca84 100644 --- a/sample-compose/buildSrc/src/main/java/Versions.kt +++ b/sample-compose/buildSrc/src/main/java/Versions.kt @@ -1,12 +1,12 @@ object Versions { - const val BUILD_GRADLE_VERSION = "7.3.0" + const val BUILD_GRADLE_VERSION = "7.4.2" const val ANDROID_COMPILE_SDK_VERSION = 33 const val ANDROID_MIN_SDK_VERSION = 24 const val ANDROID_TARGET_SDK_VERSION = 33 const val ANDROID_VERSION_CODE = 1 - const val ANDROID_VERSION_NAME = "3.21.0" + const val ANDROID_VERSION_NAME = "3.22.0" // Dependencies (Alphabet sorted) const val ACCOMPANIST_PERMISSIONS_VERSION = "0.30.1" diff --git a/sample-compose/data/src/main/java/co/nimblehq/sample/compose/data/response/Response.kt b/sample-compose/data/src/main/java/co/nimblehq/sample/compose/data/response/Response.kt index 8204bd9a4..703648033 100644 --- a/sample-compose/data/src/main/java/co/nimblehq/sample/compose/data/response/Response.kt +++ b/sample-compose/data/src/main/java/co/nimblehq/sample/compose/data/response/Response.kt @@ -4,9 +4,16 @@ import co.nimblehq.sample.compose.domain.model.Model import com.squareup.moshi.Json data class Response( - @Json(name = "id") val id: Int? + @Json(name = "id") + val id: Int?, + // A sample to ensure @Json annotation work properly with a differ between field name and JSON key name + @Json(name = "username") + val userName: String?, ) -private fun Response.toModel() = Model(id = this.id) +private fun Response.toModel() = Model( + id = this.id, + username = this.userName, +) fun List.toModels() = this.map { it.toModel() } diff --git a/sample-compose/data/src/test/java/co/nimblehq/sample/compose/data/repository/RepositoryTest.kt b/sample-compose/data/src/test/java/co/nimblehq/sample/compose/data/repository/RepositoryTest.kt index d0ae0fcfa..8e5afc778 100644 --- a/sample-compose/data/src/test/java/co/nimblehq/sample/compose/data/repository/RepositoryTest.kt +++ b/sample-compose/data/src/test/java/co/nimblehq/sample/compose/data/repository/RepositoryTest.kt @@ -1,8 +1,8 @@ package co.nimblehq.sample.compose.data.repository -import co.nimblehq.sample.compose.data.response.Response import co.nimblehq.sample.compose.data.response.toModels import co.nimblehq.sample.compose.data.service.ApiService +import co.nimblehq.sample.compose.data.test.MockUtil import co.nimblehq.sample.compose.domain.repository.Repository import io.kotest.matchers.shouldBe import io.mockk.coEvery @@ -20,8 +20,6 @@ class RepositoryTest { private lateinit var mockService: ApiService private lateinit var repository: Repository - private val response = Response(id = 1) - @Before fun setUp() { mockService = mockk() @@ -30,7 +28,7 @@ class RepositoryTest { @Test fun `When request successful, it returns success`() = runTest { - val expected = listOf(response) + val expected = MockUtil.responses coEvery { mockService.getResponses() } returns expected repository.getModels().collect { diff --git a/sample-compose/data/src/test/java/co/nimblehq/sample/compose/data/test/MockUtil.kt b/sample-compose/data/src/test/java/co/nimblehq/sample/compose/data/test/MockUtil.kt index 0c0d88b35..4a2ca5142 100644 --- a/sample-compose/data/src/test/java/co/nimblehq/sample/compose/data/test/MockUtil.kt +++ b/sample-compose/data/src/test/java/co/nimblehq/sample/compose/data/test/MockUtil.kt @@ -29,4 +29,11 @@ object MockUtil { val errorResponse = ErrorResponse( message = "message" ) + + val responses = listOf( + co.nimblehq.sample.compose.data.response.Response( + id = 1, + userName = "name1", + ) + ) } diff --git a/sample-compose/domain/src/main/java/co/nimblehq/sample/compose/domain/model/Model.kt b/sample-compose/domain/src/main/java/co/nimblehq/sample/compose/domain/model/Model.kt index b77e13bc7..559f5a236 100644 --- a/sample-compose/domain/src/main/java/co/nimblehq/sample/compose/domain/model/Model.kt +++ b/sample-compose/domain/src/main/java/co/nimblehq/sample/compose/domain/model/Model.kt @@ -1,5 +1,6 @@ package co.nimblehq.sample.compose.domain.model data class Model( - val id: Int? + val id: Int?, + val username: String?, ) diff --git a/sample-compose/domain/src/test/java/co/nimblehq/sample/compose/domain/test/MockUtil.kt b/sample-compose/domain/src/test/java/co/nimblehq/sample/compose/domain/test/MockUtil.kt new file mode 100644 index 000000000..f0fbd33da --- /dev/null +++ b/sample-compose/domain/src/test/java/co/nimblehq/sample/compose/domain/test/MockUtil.kt @@ -0,0 +1,13 @@ +package co.nimblehq.sample.compose.domain.test + +import co.nimblehq.sample.compose.domain.model.Model + +object MockUtil { + + val models = listOf( + Model( + id = 1, + username = "name1", + ) + ) +} diff --git a/sample-compose/domain/src/test/java/co/nimblehq/sample/compose/domain/usecase/GetModelsUseCaseTest.kt b/sample-compose/domain/src/test/java/co/nimblehq/sample/compose/domain/usecase/GetModelsUseCaseTest.kt index 95fb58b26..1a64b64d4 100644 --- a/sample-compose/domain/src/test/java/co/nimblehq/sample/compose/domain/usecase/GetModelsUseCaseTest.kt +++ b/sample-compose/domain/src/test/java/co/nimblehq/sample/compose/domain/usecase/GetModelsUseCaseTest.kt @@ -1,12 +1,15 @@ package co.nimblehq.sample.compose.domain.usecase -import co.nimblehq.sample.compose.domain.model.Model import co.nimblehq.sample.compose.domain.repository.Repository +import co.nimblehq.sample.compose.domain.test.MockUtil import io.kotest.matchers.shouldBe import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -17,8 +20,6 @@ class GetModelsUseCaseTest { private lateinit var mockRepository: Repository private lateinit var getModelsUseCase: GetModelsUseCase - private val model = Model(id = 1) - @Before fun setUp() { mockRepository = mockk() @@ -27,7 +28,7 @@ class GetModelsUseCaseTest { @Test fun `When request successful, it returns success`() = runTest { - val expected = listOf(model) + val expected = MockUtil.models every { mockRepository.getModels() } returns flowOf(expected) getModelsUseCase().collect { diff --git a/sample-compose/gradle/wrapper/gradle-wrapper.properties b/sample-compose/gradle/wrapper/gradle-wrapper.properties index 7645e290e..721770ea0 100644 --- a/sample-compose/gradle/wrapper/gradle-wrapper.properties +++ b/sample-compose/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Wed Jun 28 08:46:12 ICT 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip diff --git a/sample-xml/app/proguard-rules.pro b/sample-xml/app/proguard-rules.pro index 2f9dc5a47..e10060a5f 100644 --- a/sample-xml/app/proguard-rules.pro +++ b/sample-xml/app/proguard-rules.pro @@ -19,3 +19,7 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile + +# Data class +-keepclassmembers class co.nimblehq.sample.xml.data.request.** { *; } +-keepclassmembers class co.nimblehq.sample.xml.data.response.** { *; } diff --git a/sample-xml/app/src/debug/AndroidManifest.xml b/sample-xml/app/src/debug/AndroidManifest.xml index 3711326c8..6a570c323 100644 --- a/sample-xml/app/src/debug/AndroidManifest.xml +++ b/sample-xml/app/src/debug/AndroidManifest.xml @@ -2,6 +2,9 @@ + + + Int = { + if (project.hasProperty("versionCode")) { + (project.property("versionCode") as String).toInt() + } else { + Versions.ANDROID_VERSION_CODE + } +} android { signingConfigs { @@ -35,7 +44,7 @@ android { applicationId = "co.nimblehq.template.compose" minSdk = Versions.ANDROID_MIN_SDK_VERSION targetSdk = Versions.ANDROID_TARGET_SDK_VERSION - versionCode = Versions.ANDROID_VERSION_CODE + versionCode = getVersionCode() versionName = Versions.ANDROID_VERSION_NAME testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -133,6 +142,8 @@ dependencies { implementation("androidx.datastore:datastore-preferences:${Versions.ANDROIDX_DATASTORE_PREFERENCES_VERSION}") + implementation(platform("com.google.firebase:firebase-bom:${Versions.FIREBASE_BOM_VERSION}")) + implementation("androidx.navigation:navigation-compose:${Versions.COMPOSE_NAVIGATION_VERSION}") implementation("com.google.accompanist:accompanist-permissions:${Versions.ACCOMPANIST_PERMISSIONS_VERSION}") diff --git a/template-compose/app/proguard-rules.pro b/template-compose/app/proguard-rules.pro index 2f9dc5a47..eb250ec43 100644 --- a/template-compose/app/proguard-rules.pro +++ b/template-compose/app/proguard-rules.pro @@ -19,3 +19,7 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile + +# Data class +-keepclassmembers class co.nimblehq.template.compose.data.request.** { *; } +-keepclassmembers class co.nimblehq.template.compose.data.response.** { *; } diff --git a/template-compose/app/src/debug/AndroidManifest.xml b/template-compose/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..c10e37a53 --- /dev/null +++ b/template-compose/app/src/debug/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/template-compose/app/src/test/java/co/nimblehq/template/compose/test/MockUtil.kt b/template-compose/app/src/test/java/co/nimblehq/template/compose/test/MockUtil.kt new file mode 100644 index 000000000..60e91c791 --- /dev/null +++ b/template-compose/app/src/test/java/co/nimblehq/template/compose/test/MockUtil.kt @@ -0,0 +1,12 @@ +package co.nimblehq.template.compose.test + +import co.nimblehq.template.compose.domain.model.Model + +object MockUtil { + + val models = listOf( + Model(id = 1), + Model(id = 2), + Model(id = 3), + ) +} diff --git a/template-compose/app/src/test/java/co/nimblehq/template/compose/ui/screens/home/HomeScreenTest.kt b/template-compose/app/src/test/java/co/nimblehq/template/compose/ui/screens/home/HomeScreenTest.kt index 71a0589af..25514e885 100644 --- a/template-compose/app/src/test/java/co/nimblehq/template/compose/ui/screens/home/HomeScreenTest.kt +++ b/template-compose/app/src/test/java/co/nimblehq/template/compose/ui/screens/home/HomeScreenTest.kt @@ -5,8 +5,8 @@ import androidx.compose.ui.test.* import androidx.compose.ui.test.junit4.* import androidx.test.ext.junit.rules.ActivityScenarioRule import co.nimblehq.template.compose.R -import co.nimblehq.template.compose.domain.model.Model import co.nimblehq.template.compose.domain.usecase.UseCase +import co.nimblehq.template.compose.test.MockUtil import co.nimblehq.template.compose.ui.AppDestination import co.nimblehq.template.compose.ui.screens.BaseScreenTest import co.nimblehq.template.compose.ui.screens.MainActivity @@ -35,9 +35,7 @@ class HomeScreenTest : BaseScreenTest() { @Before fun setUp() { - every { mockUseCase() } returns flowOf( - listOf(Model(1), Model(2), Model(3)) - ) + every { mockUseCase() } returns flowOf(MockUtil.models) } @Test diff --git a/template-compose/app/src/test/java/co/nimblehq/template/compose/ui/screens/home/HomeViewModelTest.kt b/template-compose/app/src/test/java/co/nimblehq/template/compose/ui/screens/home/HomeViewModelTest.kt index a49ba88ce..842b01a52 100644 --- a/template-compose/app/src/test/java/co/nimblehq/template/compose/ui/screens/home/HomeViewModelTest.kt +++ b/template-compose/app/src/test/java/co/nimblehq/template/compose/ui/screens/home/HomeViewModelTest.kt @@ -1,10 +1,10 @@ package co.nimblehq.template.compose.ui.screens.home import app.cash.turbine.test -import co.nimblehq.template.compose.domain.model.Model import co.nimblehq.template.compose.domain.usecase.UseCase import co.nimblehq.template.compose.model.toUiModel import co.nimblehq.template.compose.test.CoroutineTestRule +import co.nimblehq.template.compose.test.MockUtil import co.nimblehq.template.compose.util.DispatchersProvider import io.kotest.matchers.shouldBe import io.mockk.every @@ -25,11 +25,9 @@ class HomeViewModelTest { private lateinit var viewModel: HomeViewModel - private val models = listOf(Model(1), Model(2), Model(3)) - @Before fun setUp() { - every { mockUseCase() } returns flowOf(models) + every { mockUseCase() } returns flowOf(MockUtil.models) initViewModel() } @@ -37,7 +35,7 @@ class HomeViewModelTest { @Test fun `When loading models successfully, it shows the model list`() = runTest { viewModel.uiModels.test { - expectMostRecentItem() shouldBe models.map { it.toUiModel() } + expectMostRecentItem() shouldBe MockUtil.models.map { it.toUiModel() } } } diff --git a/template-compose/build.gradle.kts b/template-compose/build.gradle.kts index c2d513a97..242a2e250 100644 --- a/template-compose/build.gradle.kts +++ b/template-compose/build.gradle.kts @@ -9,6 +9,7 @@ buildscript { classpath("com.android.tools.build:gradle:${Versions.BUILD_GRADLE_VERSION}") classpath("com.google.dagger:hilt-android-gradle-plugin:${Versions.HILT_VERSION}") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.KOTLIN_VERSION}") + classpath("com.google.gms:google-services:${Versions.GOOGLE_SERVICES_VERSION}") } } @@ -20,8 +21,8 @@ plugins { allprojects { repositories { google() - maven(url = "https://jitpack.io") mavenCentral() + maven { url = uri("https://www.jitpack.io") } } } diff --git a/template-compose/buildSrc/src/main/java/Versions.kt b/template-compose/buildSrc/src/main/java/Versions.kt index f3caa22b1..106e2dfd5 100644 --- a/template-compose/buildSrc/src/main/java/Versions.kt +++ b/template-compose/buildSrc/src/main/java/Versions.kt @@ -1,5 +1,5 @@ object Versions { - const val BUILD_GRADLE_VERSION = "7.3.0" + const val BUILD_GRADLE_VERSION = "7.4.2" const val ANDROID_COMPILE_SDK_VERSION = 33 const val ANDROID_MIN_SDK_VERSION = 24 @@ -21,6 +21,9 @@ object Versions { const val COMPOSE_COMPILER_VERSION = "1.4.7" const val COMPOSE_NAVIGATION_VERSION = "2.5.3" + const val FIREBASE_BOM_VERSION = "32.1.1" + const val GOOGLE_SERVICES_VERSION = "4.3.15" + const val HILT_VERSION = "2.44" const val HILT_NAVIGATION_COMPOSE_VERSION = "1.0.0" diff --git a/template-compose/data/src/test/java/co/nimblehq/template/compose/data/repository/RepositoryTest.kt b/template-compose/data/src/test/java/co/nimblehq/template/compose/data/repository/RepositoryTest.kt index 50d91f077..137167a1e 100644 --- a/template-compose/data/src/test/java/co/nimblehq/template/compose/data/repository/RepositoryTest.kt +++ b/template-compose/data/src/test/java/co/nimblehq/template/compose/data/repository/RepositoryTest.kt @@ -1,8 +1,8 @@ package co.nimblehq.template.compose.data.repository -import co.nimblehq.template.compose.data.response.Response import co.nimblehq.template.compose.data.response.toModels import co.nimblehq.template.compose.data.service.ApiService +import co.nimblehq.template.compose.data.test.MockUtil import co.nimblehq.template.compose.domain.repository.Repository import io.kotest.matchers.shouldBe import io.mockk.coEvery @@ -20,8 +20,6 @@ class RepositoryTest { private lateinit var mockService: ApiService private lateinit var repository: Repository - private val response = Response(id = 1) - @Before fun setUp() { mockService = mockk() @@ -30,7 +28,7 @@ class RepositoryTest { @Test fun `When request successful, it returns success`() = runTest { - val expected = listOf(response) + val expected = MockUtil.responses coEvery { mockService.getResponses() } returns expected repository.getModels().collect { diff --git a/template-compose/data/src/test/java/co/nimblehq/template/compose/data/test/MockUtil.kt b/template-compose/data/src/test/java/co/nimblehq/template/compose/data/test/MockUtil.kt index 4365e05f0..b94b35c78 100644 --- a/template-compose/data/src/test/java/co/nimblehq/template/compose/data/test/MockUtil.kt +++ b/template-compose/data/src/test/java/co/nimblehq/template/compose/data/test/MockUtil.kt @@ -29,4 +29,8 @@ object MockUtil { val errorResponse = ErrorResponse( message = "message" ) + + val responses = listOf( + co.nimblehq.template.compose.data.response.Response(id = 1) + ) } diff --git a/template-compose/domain/src/test/java/co/nimblehq/template/compose/domain/test/MockUtil.kt b/template-compose/domain/src/test/java/co/nimblehq/template/compose/domain/test/MockUtil.kt new file mode 100644 index 000000000..f11ab0ba1 --- /dev/null +++ b/template-compose/domain/src/test/java/co/nimblehq/template/compose/domain/test/MockUtil.kt @@ -0,0 +1,10 @@ +package co.nimblehq.template.compose.domain.test + +import co.nimblehq.template.compose.domain.model.Model + +object MockUtil { + + val models = listOf( + Model(id = 1) + ) +} diff --git a/template-compose/domain/src/test/java/co/nimblehq/template/compose/domain/usecase/UseCaseTest.kt b/template-compose/domain/src/test/java/co/nimblehq/template/compose/domain/usecase/UseCaseTest.kt index e4c09cec8..7dc0a17ae 100644 --- a/template-compose/domain/src/test/java/co/nimblehq/template/compose/domain/usecase/UseCaseTest.kt +++ b/template-compose/domain/src/test/java/co/nimblehq/template/compose/domain/usecase/UseCaseTest.kt @@ -1,9 +1,10 @@ package co.nimblehq.template.compose.domain.usecase -import co.nimblehq.template.compose.domain.model.Model import co.nimblehq.template.compose.domain.repository.Repository +import co.nimblehq.template.compose.domain.test.MockUtil import io.kotest.matchers.shouldBe -import io.mockk.* +import io.mockk.every +import io.mockk.mockk import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.* import kotlinx.coroutines.test.runTest @@ -16,8 +17,6 @@ class UseCaseTest { private lateinit var mockRepository: Repository private lateinit var useCase: UseCase - private val model = Model(id = 1) - @Before fun setUp() { mockRepository = mockk() @@ -26,7 +25,7 @@ class UseCaseTest { @Test fun `When request successful, it returns success`() = runTest { - val expected = listOf(model) + val expected = MockUtil.models every { mockRepository.getModels() } returns flowOf(expected) useCase().collect { diff --git a/template-compose/gradle/wrapper/gradle-wrapper.properties b/template-compose/gradle/wrapper/gradle-wrapper.properties index e71dcae46..721770ea0 100644 --- a/template-compose/gradle/wrapper/gradle-wrapper.properties +++ b/template-compose/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Oct 11 23:57:05 ICT 2022 +#Wed Jun 28 08:46:12 ICT 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/template-xml/app/proguard-rules.pro b/template-xml/app/proguard-rules.pro index 2f9dc5a47..415369ff0 100644 --- a/template-xml/app/proguard-rules.pro +++ b/template-xml/app/proguard-rules.pro @@ -19,3 +19,7 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile + +# Data class +-keepclassmembers class co.nimblehq.template.xml.data.request.** { *; } +-keepclassmembers class co.nimblehq.template.xml.data.response.** { *; } diff --git a/template-xml/app/src/debug/AndroidManifest.xml b/template-xml/app/src/debug/AndroidManifest.xml index 85bb1684c..fd3d72658 100644 --- a/template-xml/app/src/debug/AndroidManifest.xml +++ b/template-xml/app/src/debug/AndroidManifest.xml @@ -2,6 +2,9 @@ + + +