Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit Tests - Android + Kotlin #729

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 45 additions & 5 deletions src/SDK/Language/Android.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,22 +108,42 @@ public function getFiles(): array
[
'scope' => 'default',
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/Permission.kt',
'template' => '/android/library/src/main/java/io/appwrite/Permission.kt.twig',
'template' => '/kotlin/src/main/kotlin/io/appwrite/Permission.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/test/java/{{ sdk.namespace | caseSlash }}/PermissionTest.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/PermissionTest.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/Role.kt',
'template' => '/android/library/src/main/java/io/appwrite/Role.kt.twig',
'template' => '/kotlin/src/main/kotlin/io/appwrite/Role.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/test/java/{{ sdk.namespace | caseSlash }}/RoleTest.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/RoleTest.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/ID.kt',
'template' => '/android/library/src/main/java/io/appwrite/ID.kt.twig',
'template' => '/kotlin/src/main/kotlin/io/appwrite/ID.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/test/java/{{ sdk.namespace | caseSlash }}/IDTest.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/IDTest.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/Query.kt',
'template' => '/android/library/src/main/java/io/appwrite/Query.kt.twig',
'template' => '/kotlin/src/main/kotlin/io/appwrite/Query.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/test/java/{{ sdk.namespace | caseSlash }}/QueryTest.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/QueryTest.kt.twig',
],
[
'scope' => 'default',
Expand Down Expand Up @@ -175,6 +195,11 @@ public function getFiles(): array
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/KeepAliveService.kt',
'template' => '/android/library/src/main/java/io/appwrite/KeepAliveService.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/Response.kt',
'template' => '/kotlin/src/main/kotlin/io/appwrite/Response.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/views/CallbackActivity.kt',
Expand Down Expand Up @@ -225,6 +250,16 @@ public function getFiles(): array
'destination' => '/library/src/main/AndroidManifest.xml',
'template' => '/android/library/src/main/AndroidManifest.xml.twig',
],
[
'scope' => 'service',
'destination' => '/library/src/test/java/{{ sdk.namespace | caseSlash }}/services/{{ service.name | caseUcfirst }}ServiceTest.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/services/ServiceTest.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/test/java/{{ sdk.namespace | caseSlash }}/cookies/CookiesTest.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/cookies/CookiesTest.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/build.gradle',
Expand Down Expand Up @@ -385,7 +420,12 @@ public function getFiles(): array
[
'scope' => 'definition',
'destination' => 'library/src/main/java/io/appwrite/models/{{ definition.name | caseUcfirst }}.kt',
'template' => '/android/library/src/main/java/io/appwrite/models/Model.kt.twig',
'template' => '/kotlin/src/main/kotlin/io/appwrite/models/Model.kt.twig',
],
[
'scope' => 'definition',
'destination' => 'library/src/test/java/io/appwrite/models/{{ definition.name | caseUcfirst }}Test.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/models/ModelTest.kt.twig',
],
];
}
Expand Down
39 changes: 37 additions & 2 deletions src/SDK/Language/Kotlin.php
Original file line number Diff line number Diff line change
Expand Up @@ -353,25 +353,50 @@ public function getFiles(): array
'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/Permission.kt',
'template' => '/kotlin/src/main/kotlin/io/appwrite/Permission.kt.twig',
],
[
'scope' => 'default',
'destination' => '/src/test/kotlin/{{ sdk.namespace | caseSlash }}/PermissionTest.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/PermissionTest.kt.twig',
],
[
'scope' => 'default',
'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/Role.kt',
'template' => '/kotlin/src/main/kotlin/io/appwrite/Role.kt.twig',
],
[
'scope' => 'default',
'destination' => '/src/test/kotlin/{{ sdk.namespace | caseSlash }}/RoleTest.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/RoleTest.kt.twig',
],
[
'scope' => 'default',
'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/ID.kt',
'template' => '/kotlin/src/main/kotlin/io/appwrite/ID.kt.twig',
],
[
'scope' => 'default',
'destination' => '/src/test/kotlin/{{ sdk.namespace | caseSlash }}/IDTest.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/IDTest.kt.twig',
],
[
'scope' => 'default',
'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/Query.kt',
'template' => '/kotlin/src/main/kotlin/io/appwrite/Query.kt.twig',
],
[
'scope' => 'default',
'destination' => '/src/test/kotlin/{{ sdk.namespace | caseSlash }}/QueryTest.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/QueryTest.kt.twig',
],
[
'scope' => 'default',
'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/Response.kt',
'template' => '/kotlin/src/main/kotlin/io/appwrite/Response.kt.twig',
],
[
'scope' => 'default',
'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/coroutines/Callback.kt',
'template' => '/android/library/src/main/java/io/appwrite/coroutines/Callback.kt.twig',
'template' => '/kotlin/src/main/kotlin/io/appwrite/coroutines/Callback.kt.twig',
],
[
'scope' => 'default',
Expand Down Expand Up @@ -404,6 +429,11 @@ public function getFiles(): array
'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/services/{{service.name | caseUcfirst}}.kt',
'template' => '/kotlin/src/main/kotlin/io/appwrite/services/ServiceTemplate.kt.twig',
],
[
'scope' => 'service',
'destination' => '/src/test/kotlin/{{ sdk.namespace | caseSlash }}/services/{{service.name | caseUcfirst}}ServiceTest.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/services/ServiceTest.kt.twig',
],
[
'scope' => 'default',
'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/models/InputFile.kt',
Expand All @@ -419,6 +449,11 @@ public function getFiles(): array
'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/models/{{ definition.name | caseUcfirst }}.kt',
'template' => '/kotlin/src/main/kotlin/io/appwrite/models/Model.kt.twig',
],
[
'scope' => 'definition',
'destination' => '/src/test/kotlin/{{ sdk.namespace | caseSlash }}/models/{{ definition.name | caseUcfirst }}Test.kt',
'template' => '/kotlin/src/test/kotlin/io/appwrite/models/ModelTest.kt.twig',
],
];
}

Expand All @@ -443,7 +478,7 @@ public function getFilters(): array
protected function getReturnType(array $method, array $spec, string $namespace, string $generic = 'T'): string
{
if ($method['type'] === 'webAuth') {
return 'Bool';
return 'Boolean';
}
if ($method['type'] === 'location') {
return 'ByteArray';
Expand Down
2 changes: 1 addition & 1 deletion templates/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Tue Jun 01 15:55:54 IST 2021
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
17 changes: 14 additions & 3 deletions templates/android/library/build.gradle.twig
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ android {
consumerProguardFiles("consumer-rules.pro")
}

testOptions {
unitTests.includeAndroidResources = true
}

buildTypes {
release {
minifyEnabled false
Expand Down Expand Up @@ -70,11 +74,18 @@ dependencies {
implementation("androidx.activity:activity-ktx:1.6.1")
implementation("androidx.browser:browser:1.4.0")

testImplementation 'junit:junit:4.13.2'
testImplementation "org.jetbrains.kotlin:kotlin-test"
testImplementation "io.mockk:mockk:1.13.7"
testImplementation "androidx.test.ext:junit-ktx:1.1.5"
testImplementation "androidx.test:core-ktx:1.5.0"
testImplementation "org.robolectric:robolectric:4.5.1"
testApi("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.1")
testImplementation 'io.github.ivanshafran:shared-preferences-mock:1.2.4'
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3"
testImplementation "androidx.arch.core:core-testing:2.2.0"
}

tasks.withType(Test).configureEach {
useJUnit()
jvmArgs('-XX:+StartAttachListener')
}

apply from: "${rootProject.projectDir}/scripts/publish-module.gradle"
33 changes: 19 additions & 14 deletions templates/android/library/src/main/java/io/appwrite/Client.kt.twig
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
import okhttp3.Response as Okhttp3Response

class Client @JvmOverloads constructor(
context: Context,
Expand Down Expand Up @@ -266,7 +267,10 @@ class Client @JvmOverloads constructor(
.get()
.build()

return awaitResponse(request, responseType, converter)
val response = awaitResponse(request, responseType)

@Suppress("UNCHECKED_CAST")
return converter?.invoke(response.data) ?: response.data as T
}

val body = if (MultipartBody.FORM.toString() == headers["content-type"]) {
Expand Down Expand Up @@ -303,7 +307,10 @@ class Client @JvmOverloads constructor(
.method(method, body)
.build()

return awaitResponse(request, responseType, converter)
val response = awaitResponse(request, responseType)

@Suppress("UNCHECKED_CAST")
return converter?.invoke(response.data) ?: response.data as T
}

/**
Expand Down Expand Up @@ -441,11 +448,10 @@ class Client @JvmOverloads constructor(
* @return [T]
*/
@Throws({{ spec.title | caseUcfirst }}Exception::class)
private suspend fun <T> awaitResponse(
internal suspend fun <T> awaitResponse(
request: Request,
responseType: Class<T>,
converter: ((Any) -> T)? = null
) = suspendCancellableCoroutine<T> {
) = suspendCancellableCoroutine<Response<Any>> {
http.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
if (it.isCancelled) {
Expand All @@ -454,8 +460,7 @@ class Client @JvmOverloads constructor(
it.cancel(e)
}

@Suppress("UNCHECKED_CAST")
override fun onResponse(call: Call, response: Response) {
override fun onResponse(call: Call, response: Okhttp3Response) {
if (!response.isSuccessful) {
val body = response.body!!
.charStream()
Expand All @@ -481,19 +486,19 @@ class Client @JvmOverloads constructor(
}
when {
responseType == Boolean::class.java -> {
it.resume(true as T)
it.resume(Response(true))
return
}
responseType == ByteArray::class.java -> {
it.resume(response.body!!
val data = response.body!!
.byteStream()
.buffered()
.use(BufferedInputStream::readBytes) as T
)
.use(BufferedInputStream::readBytes)
it.resume(Response(data))
return
}
response.body == null -> {
it.resume(true as T)
it.resume(Response(true))
return
}
}
Expand All @@ -502,15 +507,15 @@ class Client @JvmOverloads constructor(
.buffered()
.use(BufferedReader::readText)
if (body.isEmpty()) {
it.resume(true as T)
it.resume(Response(true))
return
}
val map = gson.fromJson<Any>(
body,
object : TypeToken<Any>(){}.type
)
it.resume(
converter?.invoke(map) ?: map as T
Response(map)
)
}
})
Expand Down
10 changes: 0 additions & 10 deletions templates/android/library/src/main/java/io/appwrite/ID.kt.twig

This file was deleted.

This file was deleted.

Loading
Loading