diff --git a/app/build.gradle b/app/build.gradle index e515992..2605eeb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,9 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' + id 'kotlin-kapt' + id 'com.google.dagger.hilt.android' + id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") } android { @@ -24,11 +27,16 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } + kotlinOptions { - jvmTarget = '17' + jvmTarget = '1.8' + } + + buildFeatures { + buildConfig = true } } @@ -38,7 +46,30 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'com.google.android.material:material:1.12.0' implementation 'androidx.constraintlayout:constraintlayout:2.2.0' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.8.7' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7' + implementation 'androidx.fragment:fragment-ktx:1.8.5' + implementation 'androidx.navigation:navigation-fragment-ktx:2.8.5' + implementation 'androidx.navigation:navigation-ui-ktx:2.8.5' + implementation 'com.squareup.okhttp3:okhttp:4.10.0' + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.2.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' + + testImplementation 'org.mockito:mockito-core:4.0.0' + androidTestImplementation 'org.mockito:mockito-android:3.10.0' + + implementation "com.google.dagger:hilt-android:2.55" + kapt "com.google.dagger:hilt-compiler:2.55" + + androidTestImplementation "com.squareup.okhttp3:mockwebserver:4.6.0" + + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.retrofit2:converter-gson:2.5.0' +} + +kapt { + correctErrorTypes true } \ No newline at end of file diff --git a/app/src/androidTest/java/ru/otus/basicarchitecture/ui/address/AddressViewModelTest.kt b/app/src/androidTest/java/ru/otus/basicarchitecture/ui/address/AddressViewModelTest.kt new file mode 100644 index 0000000..fff3458 --- /dev/null +++ b/app/src/androidTest/java/ru/otus/basicarchitecture/ui/address/AddressViewModelTest.kt @@ -0,0 +1,81 @@ +package ru.otus.basicarchitecture.ui.address + +import kotlinx.coroutines.runBlocking +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.anyString +import org.mockito.junit.MockitoJUnitRunner +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import ru.otus.basicarchitecture.ui.data.AddressData +import ru.otus.basicarchitecture.ui.data.AddressIP +import ru.otus.basicarchitecture.ui.data.RetrofitClient +import ru.otus.basicarchitecture.ui.data.WizardCache + +@RunWith(MockitoJUnitRunner::class) +class AddressViewModelTest { + private lateinit var server: MockWebServer + private lateinit var viewModel: AddressViewModel + private lateinit var retrofitClient: RetrofitClient + + @Before + fun set() { + server = MockWebServer() + val wizardCache = WizardCache() + val addressData = AddressData() + retrofitClient = RetrofitClient() + + retrofitClient.apiService = Retrofit.Builder() + .baseUrl(server.url("/")) + .addConverterFactory(GsonConverterFactory.create()) + .build() + .create(AddressIP::class.java) + + viewModel = AddressViewModel(wizardCache, addressData, retrofitClient) + } + + @Test + fun getDataNotice() { + runBlocking { + + val response = MockResponse().setResponseCode(200).setBody( + """ + { + "suggestions": [ + { + "value": "г Москва, ул Хабаровская", + }, + ] + } + + """.trimIndent() + ) + server.enqueue(response) + viewModel.getDataNotice(anyString()) + + val result = viewModel.addressDataArray.isEmpty() + val exceptedValue = true + assertEquals(exceptedValue, result) + } + } + + @Test + fun setAddress() { + + viewModel.setAddress("Москва") + + val result = viewModel.wizardCache.personAddress + val exceptedValue = "Москва" + assertEquals(exceptedValue, result) + } + + @After + fun shutdown() { + server.shutdown() + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/ru/otus/basicarchitecture/ui/authorization/AuthorizationViewModelTest.kt b/app/src/androidTest/java/ru/otus/basicarchitecture/ui/authorization/AuthorizationViewModelTest.kt new file mode 100644 index 0000000..2c0dac9 --- /dev/null +++ b/app/src/androidTest/java/ru/otus/basicarchitecture/ui/authorization/AuthorizationViewModelTest.kt @@ -0,0 +1,43 @@ +package ru.otus.basicarchitecture.ui.authorization + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import ru.otus.basicarchitecture.ui.data.WizardCache + +@RunWith(AndroidJUnit4::class) +class AuthorizationViewModelTest { + + private lateinit var viewModel: AuthorizationViewModel + + @Before + fun set() { + val wizardCache = WizardCache() + viewModel = AuthorizationViewModel(wizardCache) + viewModel.setCurrentDate(1, 1, 2018) + } + + @Test + fun ageVerification() { + + runBlocking { + + withContext(Dispatchers.Main) { + val day = 1 + val month = 1 + val year = 2000 + + viewModel.ageVerification(day, month, year) + val result = viewModel.anAdult.value + + val exceptedValue = true + assertEquals(exceptedValue, result) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ea17fa5..7441b79 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,10 @@ + + + tools:targetApi="34"> + diff --git a/app/src/main/java/ru/otus/basicarchitecture/MainActivity.kt b/app/src/main/java/ru/otus/basicarchitecture/MainActivity.kt index 623aba9..080ecdb 100644 --- a/app/src/main/java/ru/otus/basicarchitecture/MainActivity.kt +++ b/app/src/main/java/ru/otus/basicarchitecture/MainActivity.kt @@ -2,7 +2,9 @@ package ru.otus.basicarchitecture import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/ru/otus/basicarchitecture/ui/MyHilt.kt b/app/src/main/java/ru/otus/basicarchitecture/ui/MyHilt.kt new file mode 100644 index 0000000..0d72071 --- /dev/null +++ b/app/src/main/java/ru/otus/basicarchitecture/ui/MyHilt.kt @@ -0,0 +1,11 @@ +package ru.otus.basicarchitecture.ui + +import android.app.Application +import dagger.hilt.android.HiltAndroidApp +import ru.otus.basicarchitecture.ui.data.WizardCache +import javax.inject.Inject + +@HiltAndroidApp +class MyHilt : Application() { + +} \ No newline at end of file diff --git a/app/src/main/java/ru/otus/basicarchitecture/ui/address/AddressFragment.kt b/app/src/main/java/ru/otus/basicarchitecture/ui/address/AddressFragment.kt new file mode 100644 index 0000000..5d2486a --- /dev/null +++ b/app/src/main/java/ru/otus/basicarchitecture/ui/address/AddressFragment.kt @@ -0,0 +1,84 @@ +package ru.otus.basicarchitecture.ui.address + +import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import android.widget.AutoCompleteTextView +import android.widget.Button +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import androidx.navigation.fragment.findNavController +import com.google.android.material.textfield.TextInputLayout +import dagger.hilt.android.AndroidEntryPoint +import ru.otus.basicarchitecture.R + + +@AndroidEntryPoint +class AddressFragment : Fragment() { + + companion object { + fun newInstance() = AddressFragment() + } + + private val viewModel: AddressViewModel by viewModels() + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return inflater.inflate(R.layout.fragment_address, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + val addressTextInput = view.findViewById(R.id.addressTextInput) + val navController = findNavController() + + view.findViewById(R.id.autoCompleteTextView).apply { + threshold = 4 + addTextChangedListener(object : + TextWatcher { + override fun onTextChanged( + s: CharSequence, + start: Int, + before: Int, + count: Int + ) { + + if (s.length > 3) { + viewModel.getDataNotice(s.toString()) + val adapter = activity?.let { + ArrayAdapter( + it.baseContext, + android.R.layout.simple_dropdown_item_1line, + viewModel.addressDataArray + ) + } + setAdapter(adapter) + } + } + + override fun beforeTextChanged( + s: CharSequence, + start: Int, + count: Int, + after: Int + ) { + } + + override fun afterTextChanged(s: Editable) {} + }); + } + + view.findViewById