Skip to content

Commit 8df7fba

Browse files
Add orderby to firestore (#109)
* Add orderBy to js common * Add orderBy implementations * Added condition to get enum to string * Added tests for orderBy * Add serialization to plugins * Moved setup to each test * Added testInstrumentationRunner to firestore build.gradle.kts * Review changes * Remove duplicate orderBy * Add optional to orderBy * Add internal val to enum for js version of ascend and descend * Replace value with jsValue
1 parent de8974b commit 8df7fba

File tree

7 files changed

+117
-4
lines changed

7 files changed

+117
-4
lines changed

firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ external object firebase {
356356
fun where(field: Any, opStr: String, value: Any?): Query
357357
fun onSnapshot(next: (snapshot: QuerySnapshot) -> Unit, error: (error: Error) -> Unit): () -> Unit
358358
fun limit(limit: Double): Query
359+
fun orderBy(field: Any, direction: Any): Query
359360
}
360361

361362
open class CollectionReference : Query {

firebase-firestore/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,22 @@ version = project.property("firebase-firestore.version") as String
33
plugins {
44
id("com.android.library")
55
kotlin("multiplatform")
6+
kotlin("plugin.serialization") version "1.4.10"
67
}
78

89
android {
910
compileSdkVersion(property("targetSdkVersion") as Int)
1011
defaultConfig {
1112
minSdkVersion(property("minSdkVersion") as Int)
1213
targetSdkVersion(property("targetSdkVersion") as Int)
14+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
1315
setMultiDexEnabled(true)
1416
}
1517
sourceSets {
1618
getByName("main") {
1719
manifest.srcFile("src/androidMain/AndroidManifest.xml")
1820
}
21+
getByName("androidTest").java.srcDir(file("src/androidAndroidTest/kotlin"))
1922
}
2023
testOptions {
2124
unitTests.apply {

firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,13 @@ actual open class Query(open val android: com.google.firebase.firestore.Query) {
312312
arrayContainsAny?.let { android2.whereArrayContainsAny(path, it) } ?: android2
313313
}
314314
)
315+
316+
internal actual fun _orderBy(field: String, direction: Direction) = Query(android.orderBy(field, direction))
317+
internal actual fun _orderBy(field: FieldPath, direction: Direction) = Query(android.orderBy(field, direction))
315318
}
316319

320+
actual typealias Direction = com.google.firebase.firestore.Query.Direction
321+
317322
actual class CollectionReference(override val android: com.google.firebase.firestore.CollectionReference) : Query(android) {
318323

319324
actual val path: String

firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ expect open class Query {
6161
internal fun _where(path: FieldPath, lessThan: Any? = null, greaterThan: Any? = null, arrayContains: Any? = null): Query
6262
internal fun _where(field: String, inArray: List<Any>? = null, arrayContainsAny: List<Any>? = null): Query
6363
internal fun _where(path: FieldPath, inArray: List<Any>? = null, arrayContainsAny: List<Any>? = null): Query
64+
65+
internal fun _orderBy(field: String, direction: Direction): Query
66+
internal fun _orderBy(field: FieldPath, direction: Direction): Query
6467
}
6568

6669
fun Query.where(field: String, equalTo: Any?) = _where(field, equalTo)
@@ -70,6 +73,8 @@ fun Query.where(path: FieldPath, lessThan: Any? = null, greaterThan: Any? = null
7073
fun Query.where(field: String, inArray: List<Any>? = null, arrayContainsAny: List<Any>? = null) = _where(field, inArray, arrayContainsAny)
7174
fun Query.where(path: FieldPath, inArray: List<Any>? = null, arrayContainsAny: List<Any>? = null) = _where(path, inArray, arrayContainsAny)
7275

76+
fun Query.orderBy(field: String, direction: Direction = Direction.ASCENDING) = _orderBy(field, direction)
77+
fun Query.orderBy(field: FieldPath, direction: Direction = Direction.ASCENDING) = _orderBy(field, direction)
7378

7479
expect class WriteBatch {
7580
inline fun <reified T> set(documentRef: DocumentReference, data: T, encodeDefaults: Boolean = true, merge: Boolean = false): WriteBatch
@@ -145,6 +150,11 @@ expect enum class FirestoreExceptionCode {
145150
UNAUTHENTICATED
146151
}
147152

153+
expect enum class Direction {
154+
ASCENDING,
155+
DESCENDING
156+
}
157+
148158
expect class QuerySnapshot {
149159
val documents: List<DocumentSnapshot>
150160
val metadata: SnapshotMetadata
@@ -181,4 +191,3 @@ expect object FieldValue {
181191
fun arrayRemove(vararg elements: Any): Any
182192
}
183193

184-

firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55
package dev.gitlive.firebase.firestore
66

77
import dev.gitlive.firebase.*
8+
import kotlinx.serialization.*
89
import kotlin.test.*
910

1011
expect val context: Any
1112
expect fun runTest(test: suspend () -> Unit)
1213

1314
class FirebaseFirestoreTest {
1415

16+
@Serializable
17+
data class FirestoreTest(val prop1: String)
18+
1519
@BeforeTest
1620
fun initializeFirebase() {
1721
Firebase
@@ -29,7 +33,74 @@ class FirebaseFirestoreTest {
2933
}
3034

3135
@Test
32-
fun testClearPersistence() = runTest {
33-
Firebase.firestore.clearPersistence()
36+
fun testStringOrderBy() = runTest {
37+
setupFirestoreData()
38+
39+
val resultDocs = Firebase.firestore.collection("test").orderBy("prop1").get().documents
40+
assertEquals(3, resultDocs.size)
41+
assertEquals("aaa", resultDocs[0].get("prop1"))
42+
assertEquals("bbb", resultDocs[1].get("prop1"))
43+
assertEquals("ccc", resultDocs[2].get("prop1"))
44+
}
45+
46+
@Test
47+
fun testFieldOrderBy() = runTest {
48+
setupFirestoreData()
49+
50+
val resultDocs = Firebase.firestore.collection("test").orderBy(FieldPath("prop1")).get().documents
51+
assertEquals(3, resultDocs.size)
52+
assertEquals("aaa", resultDocs[0].get("prop1"))
53+
assertEquals("bbb", resultDocs[1].get("prop1"))
54+
assertEquals("ccc", resultDocs[2].get("prop1"))
55+
}
56+
57+
@Test
58+
fun testStringOrderByAscending() = runTest {
59+
setupFirestoreData()
60+
61+
val resultDocs = Firebase.firestore.collection("test").orderBy("prop1", Direction.ASCENDING).get().documents
62+
assertEquals(3, resultDocs.size)
63+
assertEquals("aaa", resultDocs[0].get("prop1"))
64+
assertEquals("bbb", resultDocs[1].get("prop1"))
65+
assertEquals("ccc", resultDocs[2].get("prop1"))
66+
}
67+
68+
@Test
69+
fun testFieldOrderByAscending() = runTest {
70+
setupFirestoreData()
71+
72+
val resultDocs = Firebase.firestore.collection("test").orderBy(FieldPath("prop1"), Direction.ASCENDING).get().documents
73+
assertEquals(3, resultDocs.size)
74+
assertEquals("aaa", resultDocs[0].get("prop1"))
75+
assertEquals("bbb", resultDocs[1].get("prop1"))
76+
assertEquals("ccc", resultDocs[2].get("prop1"))
77+
}
78+
79+
@Test
80+
fun testStringOrderByDescending() = runTest {
81+
setupFirestoreData()
82+
83+
val resultDocs = Firebase.firestore.collection("test").orderBy("prop1", Direction.DESCENDING).get().documents
84+
assertEquals(3, resultDocs.size)
85+
assertEquals("ccc", resultDocs[0].get("prop1"))
86+
assertEquals("bbb", resultDocs[1].get("prop1"))
87+
assertEquals("aaa", resultDocs[2].get("prop1"))
88+
}
89+
90+
@Test
91+
fun testFieldOrderByDescending() = runTest {
92+
setupFirestoreData()
93+
94+
val resultDocs = Firebase.firestore.collection("test").orderBy(FieldPath("prop1"), Direction.DESCENDING).get().documents
95+
assertEquals(3, resultDocs.size)
96+
assertEquals("ccc", resultDocs[0].get("prop1"))
97+
assertEquals("bbb", resultDocs[1].get("prop1"))
98+
assertEquals("aaa", resultDocs[2].get("prop1"))
99+
}
100+
101+
private suspend fun setupFirestoreData() {
102+
Firebase.firestore.document("test/one").set(FirestoreTest.serializer(), FirestoreTest("aaa"))
103+
Firebase.firestore.document("test/two").set(FirestoreTest.serializer(), FirestoreTest("bbb"))
104+
Firebase.firestore.document("test/three").set(FirestoreTest.serializer(), FirestoreTest("ccc"))
34105
}
35106
}

firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,13 @@ actual open class Query(open val ios: FIRQuery) {
219219
(inArray?.let { ios.queryWhereFieldPath(path, `in` = it) } ?: ios).let { ios2 ->
220220
arrayContainsAny?.let { ios2.queryWhereFieldPath(path, arrayContainsAny = arrayContainsAny) } ?: ios2
221221
}
222-
)}
222+
)
223+
224+
internal actual fun _orderBy(field: String, direction: Direction) = Query(ios.queryOrderedByField(field, direction == Direction.DESCENDING))
225+
226+
internal actual fun _orderBy(field: FieldPath, direction: Direction) = Query(ios.queryOrderedByFieldPath(field, direction == Direction.DESCENDING))
227+
228+
}
223229
@Suppress("UNCHECKED_CAST")
224230
actual class CollectionReference(override val ios: FIRCollectionReference) : Query(ios) {
225231

@@ -257,6 +263,11 @@ actual enum class FirestoreExceptionCode {
257263
UNAUTHENTICATED
258264
}
259265

266+
actual enum class Direction {
267+
ASCENDING,
268+
DESCENDING
269+
}
270+
260271
fun NSError.toException() = when(domain) {
261272
FIRFirestoreErrorDomain -> when(code) {
262273
FIRFirestoreErrorCodeOK -> FirestoreExceptionCode.OK

firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,14 @@ actual open class Query(open val js: firebase.firestore.Query) {
286286
}
287287
)
288288

289+
internal actual fun _orderBy(field: String, direction: Direction) = rethrow {
290+
Query(js.orderBy(field, direction.jsString))
291+
}
292+
293+
internal actual fun _orderBy(field: FieldPath, direction: Direction) = rethrow {
294+
Query(js.orderBy(field, direction.jsString))
295+
}
296+
289297
actual val snapshots get() = callbackFlow<QuerySnapshot> {
290298
val unsubscribe = rethrow {
291299
js.onSnapshot(
@@ -387,6 +395,11 @@ actual enum class FirestoreExceptionCode {
387395
UNAUTHENTICATED
388396
}
389397

398+
actual enum class Direction(internal val jsString : String) {
399+
ASCENDING("asc"),
400+
DESCENDING("desc");
401+
}
402+
390403
inline fun <T, R> T.rethrow(function: T.() -> R): R = dev.gitlive.firebase.firestore.rethrow { function() }
391404

392405
inline fun <R> rethrow(function: () -> R): R {

0 commit comments

Comments
 (0)