From 2e9b62b65405343cf7c263a20978e3eff9fe80f9 Mon Sep 17 00:00:00 2001 From: James Magahern Date: Sun, 6 Aug 2023 12:27:58 -0700 Subject: [PATCH] Adds backend module, tests for /version and /conversations (not real tests yet) --- .idea/gradle.xml | 1 + .idea/kotlinc.xml | 2 +- .idea/misc.xml | 1 - app/build.gradle | 6 ++- backend/.gitignore | 1 + backend/build.gradle | 52 +++++++++++++++++++ backend/consumer-rules.pro | 0 backend/proguard-rules.pro | 21 ++++++++ .../backend/ExampleInstrumentedTest.kt | 24 +++++++++ backend/src/main/AndroidManifest.xml | 4 ++ .../buzzert/kordophone/backend/APIClient.kt | 16 ++++++ .../kordophone/backend/APIInterface.kt | 15 ++++++ .../kordophone/backend/ChatRepository.kt | 19 +++++++ .../kordophone/backend/model/Conversation.kt | 24 +++++++++ .../kordophone/backend/ExampleUnitTest.kt | 33 ++++++++++++ build.gradle | 2 +- settings.gradle | 1 + 17 files changed, 218 insertions(+), 4 deletions(-) create mode 100644 backend/.gitignore create mode 100644 backend/build.gradle create mode 100644 backend/consumer-rules.pro create mode 100644 backend/proguard-rules.pro create mode 100644 backend/src/androidTest/java/net/buzzert/kordophone/backend/ExampleInstrumentedTest.kt create mode 100644 backend/src/main/AndroidManifest.xml create mode 100644 backend/src/main/java/net/buzzert/kordophone/backend/APIClient.kt create mode 100644 backend/src/main/java/net/buzzert/kordophone/backend/APIInterface.kt create mode 100644 backend/src/main/java/net/buzzert/kordophone/backend/ChatRepository.kt create mode 100644 backend/src/main/java/net/buzzert/kordophone/backend/model/Conversation.kt create mode 100644 backend/src/test/java/net/buzzert/kordophone/backend/ExampleUnitTest.kt diff --git a/.idea/gradle.xml b/.idea/gradle.xml index a0de2a1..e3e6d33 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -12,6 +12,7 @@ diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 2b8a50f..fdf8d99 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 9f71c83..773fe0f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/app/build.gradle b/app/build.gradle index 31d8f6e..d5db5c6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -48,6 +48,10 @@ android { dependencies { implementation 'androidx.compose.material3:material3:1.1.1' + implementation 'androidx.core:core-ktx:+' + + // Kordophone lib + implementation project(':backend') // Navigation def nav_version = "2.5.3" @@ -76,7 +80,7 @@ dependencies { implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version" implementation 'androidx.compose.material:material:1.1.1' - implementation 'androidx.compose.foundation:foundation:$compose_ui_version' + implementation "androidx.compose.foundation:foundation:$compose_ui_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version" debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version" diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/backend/build.gradle b/backend/build.gradle new file mode 100644 index 0000000..aeb90cf --- /dev/null +++ b/backend/build.gradle @@ -0,0 +1,52 @@ +plugins { + id 'com.android.library' + id 'org.jetbrains.kotlin.android' +} + +android { + namespace 'net.buzzert.kordophone.backend' + compileSdk 33 + + defaultConfig { + minSdk 31 + targetSdk 33 + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles "consumer-rules.pro" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } +} + +dependencies { + + implementation 'androidx.core:core-ktx:1.8.0' + implementation 'androidx.appcompat:appcompat:1.4.1' + implementation 'com.google.android.material:material:1.5.0' + implementation 'androidx.core:core-ktx:+' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + + // Third-party + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.retrofit2:converter-gson:2.9.0' + implementation 'com.google.code.gson:gson:2.9.0' + + // https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core + implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.7.3', ext: 'pom' + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3' + testImplementation 'com.squareup.okhttp3:mockwebserver:4.9.1' +} \ No newline at end of file diff --git a/backend/consumer-rules.pro b/backend/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/backend/proguard-rules.pro b/backend/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/backend/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/backend/src/androidTest/java/net/buzzert/kordophone/backend/ExampleInstrumentedTest.kt b/backend/src/androidTest/java/net/buzzert/kordophone/backend/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..ec75aaf --- /dev/null +++ b/backend/src/androidTest/java/net/buzzert/kordophone/backend/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package net.buzzert.kordophone.backend + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("net.buzzert.kordophone.backend.test", appContext.packageName) + } +} \ No newline at end of file diff --git a/backend/src/main/AndroidManifest.xml b/backend/src/main/AndroidManifest.xml new file mode 100644 index 0000000..87c51ee --- /dev/null +++ b/backend/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/backend/src/main/java/net/buzzert/kordophone/backend/APIClient.kt b/backend/src/main/java/net/buzzert/kordophone/backend/APIClient.kt new file mode 100644 index 0000000..06785bf --- /dev/null +++ b/backend/src/main/java/net/buzzert/kordophone/backend/APIClient.kt @@ -0,0 +1,16 @@ +package net.buzzert.kordophone.backend + +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import java.net.URL + +class APIClient(baseURL: URL) { + private val retrofit: Retrofit = Retrofit.Builder() + .baseUrl(baseURL) + .addConverterFactory(GsonConverterFactory.create()) + .build() + + fun getClient(): Retrofit { + return retrofit + } +} \ No newline at end of file diff --git a/backend/src/main/java/net/buzzert/kordophone/backend/APIInterface.kt b/backend/src/main/java/net/buzzert/kordophone/backend/APIInterface.kt new file mode 100644 index 0000000..e5a63b2 --- /dev/null +++ b/backend/src/main/java/net/buzzert/kordophone/backend/APIInterface.kt @@ -0,0 +1,15 @@ +package net.buzzert.kordophone.backend + +import net.buzzert.kordophone.backend.model.Conversation +import okhttp3.ResponseBody +import retrofit2.Call +import retrofit2.Response +import retrofit2.http.GET + +interface APIInterface { + @GET("/version") + suspend fun getVersion(): ResponseBody + + @GET("/conversations") + suspend fun getConversations(): Response> +} \ No newline at end of file diff --git a/backend/src/main/java/net/buzzert/kordophone/backend/ChatRepository.kt b/backend/src/main/java/net/buzzert/kordophone/backend/ChatRepository.kt new file mode 100644 index 0000000..545e770 --- /dev/null +++ b/backend/src/main/java/net/buzzert/kordophone/backend/ChatRepository.kt @@ -0,0 +1,19 @@ +package net.buzzert.kordophone.backend + +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch +import net.buzzert.kordophone.backend.model.Conversation +import java.net.URL + +class ChatRepository(baseURL: URL) { + private val client: APIClient = APIClient(baseURL) + private val apiInterface: APIInterface = client.getClient().create(APIInterface::class.java) + + suspend fun getVersion(): String { + return apiInterface.getVersion().string() + } + + suspend fun fetchConversations(): List { + return apiInterface.getConversations().body()!! + } +} \ No newline at end of file diff --git a/backend/src/main/java/net/buzzert/kordophone/backend/model/Conversation.kt b/backend/src/main/java/net/buzzert/kordophone/backend/model/Conversation.kt new file mode 100644 index 0000000..44bef55 --- /dev/null +++ b/backend/src/main/java/net/buzzert/kordophone/backend/model/Conversation.kt @@ -0,0 +1,24 @@ +package net.buzzert.kordophone.backend.model + +import com.google.gson.annotations.SerializedName +import java.util.Date + +data class Conversation( + @SerializedName("date") + val date: Date, + + @SerializedName("participantDisplayNames") + val participants: List?, + + @SerializedName("displayName") + val displayName: String?, + + @SerializedName("unreadCount") + val unreadCount: Int, + + @SerializedName("lastMessagePreview") + val lastMessagePreview: String, + + @SerializedName("guid") + val guid: String, +) diff --git a/backend/src/test/java/net/buzzert/kordophone/backend/ExampleUnitTest.kt b/backend/src/test/java/net/buzzert/kordophone/backend/ExampleUnitTest.kt new file mode 100644 index 0000000..48bbb85 --- /dev/null +++ b/backend/src/test/java/net/buzzert/kordophone/backend/ExampleUnitTest.kt @@ -0,0 +1,33 @@ +package net.buzzert.kordophone.backend + +import kotlinx.coroutines.runBlocking +import org.junit.Test + +import org.junit.Assert.* +import java.net.URL + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + val repository = ChatRepository(URL("http://localhost:5738")) + + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } + + @Test + fun testGetVersion() = runBlocking { + val version = repository.getVersion() + println("Version: $version") + } + + @Test + fun testFetchConversations() = runBlocking { + val conversations = repository.fetchConversations() + println("Conversations: $conversations") + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8595104..6dd2ec6 100644 --- a/build.gradle +++ b/build.gradle @@ -8,5 +8,5 @@ buildscript { plugins { id 'com.android.application' version '7.4.2' apply false id 'com.android.library' version '7.4.2' apply false - id 'org.jetbrains.kotlin.android' version '1.8.0' apply false + id 'org.jetbrains.kotlin.android' version '1.9.0' apply false } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 97ed009..5d8401c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,3 +14,4 @@ dependencyResolutionManagement { } rootProject.name = "KordophoneDroid" include ':app' +include ':backend'