Skip to content

Commit fda06c3

Browse files
committed
Added tests & fixed ios nullability
1 parent a35a34e commit fda06c3

File tree

2 files changed

+257
-9
lines changed
  • firebase-firestore/src

2 files changed

+257
-9
lines changed

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

Lines changed: 253 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import kotlinx.coroutines.flow.filter
1818
import kotlinx.coroutines.flow.first
1919
import kotlinx.coroutines.test.TestResult
2020
import kotlinx.coroutines.withContext
21+
import kotlinx.serialization.KSerializer
2122
import kotlinx.serialization.Serializable
2223
import kotlinx.serialization.builtins.nullable
2324
import kotlin.random.Random
@@ -43,6 +44,7 @@ class FirebaseFirestoreTest {
4344
val time: Double = 0.0,
4445
val count: Int = 0,
4546
val list: List<String> = emptyList(),
47+
val optional: String? = null,
4648
)
4749

4850
@Serializable
@@ -51,6 +53,29 @@ class FirebaseFirestoreTest {
5153
val time: BaseTimestamp?
5254
)
5355

56+
companion object {
57+
val testOne = FirestoreTest(
58+
"aaa",
59+
0.0,
60+
1,
61+
listOf("a", "aa", "aaa"),
62+
"notNull",
63+
)
64+
val testTwo = FirestoreTest(
65+
"bbb",
66+
0.0,
67+
2,
68+
listOf("b", "bb", "ccc")
69+
)
70+
val testThree = FirestoreTest(
71+
"ccc",
72+
1.0,
73+
3,
74+
listOf("c", "cc", "ccc"),
75+
"notNull",
76+
)
77+
}
78+
5479
lateinit var firestore: FirebaseFirestore
5580

5681
@BeforeTest
@@ -523,18 +548,241 @@ class FirebaseFirestoreTest {
523548
assertEquals(setOf(DocumentWithTimestamp(futureTimestamp)), gtQueryResult)
524549
}
525550

526-
private suspend fun setupFirestoreData() {
551+
@Test
552+
fun testQueryEqualTo() = runTest {
553+
setupFirestoreData()
554+
555+
val fieldQuery = firestore
556+
.collection("testFirestoreQuerying")
557+
.where { "prop1" equalTo testOne.prop1 }
558+
559+
fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
560+
561+
val pathQuery = firestore
562+
.collection("testFirestoreQuerying")
563+
.where { FieldPath(FirestoreTest::prop1.name) equalTo testTwo.prop1 }
564+
565+
pathQuery.assertDocuments(FirestoreTest.serializer(), testTwo)
566+
567+
val nullableQuery = firestore
568+
.collection("testFirestoreQuerying")
569+
.where { FieldPath(FirestoreTest::optional.name) equalTo null }
570+
571+
nullableQuery.assertDocuments(FirestoreTest.serializer(), testTwo)
572+
}
573+
574+
@Test
575+
fun testQueryNotEqualTo() = runTest {
576+
setupFirestoreData()
577+
578+
val fieldQuery = firestore
579+
.collection("testFirestoreQuerying")
580+
.where { "prop1" notEqualTo testOne.prop1 }
581+
582+
fieldQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
583+
584+
val pathQuery = firestore
585+
.collection("testFirestoreQuerying")
586+
.where { FieldPath(FirestoreTest::prop1.name) notEqualTo testTwo.prop1 }
587+
588+
pathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testThree)
589+
590+
val nullableQuery = firestore
591+
.collection("testFirestoreQuerying")
592+
.where { FieldPath(FirestoreTest::optional.name) notEqualTo null }
593+
594+
nullableQuery.assertDocuments(FirestoreTest.serializer(), testOne, testThree)
595+
}
596+
597+
@Test
598+
fun testQueryLessThan() = runTest {
599+
setupFirestoreData()
600+
601+
val fieldQuery = firestore
602+
.collection("testFirestoreQuerying")
603+
.where { "count" lessThan testThree.count }
604+
605+
fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
606+
607+
val pathQuery = firestore
608+
.collection("testFirestoreQuerying")
609+
.where { FieldPath(FirestoreTest::count.name) lessThan testTwo.count }
610+
611+
pathQuery.assertDocuments(FirestoreTest.serializer(), testOne)
612+
}
613+
614+
@Test
615+
fun testQueryGreaterThan() = runTest {
616+
setupFirestoreData()
617+
618+
val fieldQuery = firestore
619+
.collection("testFirestoreQuerying")
620+
.where { "count" greaterThan testOne.count }
621+
622+
fieldQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
623+
624+
val pathQuery = firestore
625+
.collection("testFirestoreQuerying")
626+
.where { FieldPath(FirestoreTest::count.name) greaterThan testTwo.count }
627+
628+
pathQuery.assertDocuments(FirestoreTest.serializer(), testThree)
629+
}
630+
631+
@Test
632+
fun testQueryLessThanOrEqualTo() = runTest {
633+
setupFirestoreData()
634+
635+
val fieldQuery = firestore
636+
.collection("testFirestoreQuerying")
637+
.where { "count" lessThanOrEqualTo testOne.count }
638+
639+
fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
640+
641+
val pathQuery = firestore
642+
.collection("testFirestoreQuerying")
643+
.where { FieldPath(FirestoreTest::count.name) lessThanOrEqualTo testTwo.count }
644+
645+
pathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
646+
}
647+
648+
@Test
649+
fun testQueryGreaterThanOrEqualTo() = runTest {
650+
setupFirestoreData()
651+
652+
val fieldQuery = firestore
653+
.collection("testFirestoreQuerying")
654+
.where { "count" greaterThanOrEqualTo testThree.count }
655+
656+
fieldQuery.assertDocuments(FirestoreTest.serializer(), testThree)
657+
658+
val pathQuery = firestore
659+
.collection("testFirestoreQuerying")
660+
.where { FieldPath(FirestoreTest::count.name) greaterThanOrEqualTo testTwo.count }
661+
662+
pathQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
663+
}
664+
665+
@Test
666+
fun testQueryArrayContains() = runTest {
667+
setupFirestoreData()
668+
669+
val fieldQuery = firestore
670+
.collection("testFirestoreQuerying")
671+
.where { "list" contains "a" }
672+
673+
fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
674+
675+
val pathQuery = firestore
676+
.collection("testFirestoreQuerying")
677+
.where { FieldPath(FirestoreTest::list.name) contains "ccc" }
678+
679+
pathQuery.assertDocuments(FirestoreTest.serializer(), testThree, testTwo)
680+
}
681+
682+
@Test
683+
fun testQueryArrayContainsAny() = runTest {
684+
setupFirestoreData()
685+
686+
val fieldQuery = firestore
687+
.collection("testFirestoreQuerying")
688+
.where { "list" containsAny listOf("a", "b") }
689+
690+
fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
691+
692+
val pathQuery = firestore
693+
.collection("testFirestoreQuerying")
694+
.where { FieldPath(FirestoreTest::list.name) containsAny listOf("c", "d") }
695+
696+
pathQuery.assertDocuments(FirestoreTest.serializer(), testThree)
697+
}
698+
699+
@Test
700+
fun testQueryInArray() = runTest {
701+
setupFirestoreData()
702+
703+
val fieldQuery = firestore
704+
.collection("testFirestoreQuerying")
705+
.where { "prop1" `in` listOf("aaa", "bbb") }
706+
707+
fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
708+
709+
val pathQuery = firestore
710+
.collection("testFirestoreQuerying")
711+
.where { FieldPath(FirestoreTest::prop1.name) `in` listOf("ccc", "ddd") }
712+
713+
pathQuery.assertDocuments(FirestoreTest.serializer(), testThree)
714+
}
715+
716+
@Test
717+
fun testQueryNotInArray() = runTest {
718+
setupFirestoreData()
719+
720+
val fieldQuery = firestore
721+
.collection("testFirestoreQuerying")
722+
.where { "prop1" notIn listOf("aaa", "bbb") }
723+
724+
fieldQuery.assertDocuments(FirestoreTest.serializer(), testThree)
725+
726+
val pathQuery = firestore
727+
.collection("testFirestoreQuerying")
728+
.where { FieldPath(FirestoreTest::prop1.name) notIn listOf("ccc", "ddd") }
729+
730+
pathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
731+
}
732+
733+
@Test
734+
fun testCompoundQuery() = runTest {
735+
setupFirestoreData()
736+
737+
val andQuery = firestore
738+
.collection("testFirestoreQuerying")
739+
.where {
740+
FieldPath(FirestoreTest::prop1.name) `in` listOf("aaa", "bbb") and (FieldPath(FirestoreTest::count.name) equalTo 1)
741+
}
742+
andQuery.assertDocuments(FirestoreTest.serializer(), testOne)
743+
744+
val orQuery = firestore
745+
.collection("testFirestoreQuerying")
746+
.where {
747+
FieldPath(FirestoreTest::prop1.name) equalTo "aaa" or (FieldPath(FirestoreTest::count.name) equalTo 2)
748+
}
749+
orQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
750+
751+
val andOrQuery = firestore
752+
.collection("testFirestoreQuerying")
753+
.where {
754+
(
755+
FieldPath(FirestoreTest::prop1.name) equalTo "aaa" or
756+
(FieldPath(FirestoreTest::count.name) equalTo 2)
757+
) and (FieldPath(FirestoreTest::list.name) contains "a")
758+
}
759+
andOrQuery.assertDocuments(FirestoreTest.serializer(), testOne)
760+
}
761+
762+
private suspend fun setupFirestoreData(
763+
documentOne: FirestoreTest = testOne,
764+
documentTwo: FirestoreTest = testTwo,
765+
documentThree: FirestoreTest = testThree
766+
) {
527767
firestore.collection("testFirestoreQuerying")
528768
.document("one")
529-
.set(FirestoreTest.serializer(), FirestoreTest("aaa"))
769+
.set(FirestoreTest.serializer(), documentOne)
530770
firestore.collection("testFirestoreQuerying")
531771
.document("two")
532-
.set(FirestoreTest.serializer(), FirestoreTest("bbb"))
772+
.set(FirestoreTest.serializer(), documentTwo)
533773
firestore.collection("testFirestoreQuerying")
534774
.document("three")
535-
.set(FirestoreTest.serializer(), FirestoreTest("ccc"))
775+
.set(FirestoreTest.serializer(), documentThree)
536776
}
537-
777+
778+
private suspend fun <T> Query.assertDocuments(serializer: KSerializer<T>, vararg expected: T) {
779+
val documents = get().documents
780+
assertEquals(expected.size, documents.size)
781+
documents.forEachIndexed { index, documentSnapshot ->
782+
assertEquals(expected[index], documentSnapshot.data(serializer))
783+
}
784+
}
785+
538786
private suspend fun nonSkippedDelay(timeout: Long) = withContext(Dispatchers.Default) {
539787
delay(timeout)
540788
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,8 @@ actual open class Query(open val ios: FIRQuery) {
280280
is Filter.And -> FIRFilter.andFilterWithFilters(filters.map { it.toFIRFilter() })
281281
is Filter.Or -> FIRFilter.orFilterWithFilters(filters.map { it.toFIRFilter() })
282282
is Filter.Field -> when (constraint) {
283-
is WhereConstraint.EqualTo -> FIRFilter.filterWhereField(field, isEqualTo = constraint.safeValue ?: NSNull)
284-
is WhereConstraint.NotEqualTo -> FIRFilter.filterWhereField(field, isNotEqualTo = constraint.safeValue ?: NSNull)
283+
is WhereConstraint.EqualTo -> FIRFilter.filterWhereField(field, isEqualTo = constraint.safeValue ?: NSNull.`null`())
284+
is WhereConstraint.NotEqualTo -> FIRFilter.filterWhereField(field, isNotEqualTo = constraint.safeValue ?: NSNull.`null`())
285285
is WhereConstraint.LessThan -> FIRFilter.filterWhereField(field, isLessThan = constraint.safeValue)
286286
is WhereConstraint.GreaterThan -> FIRFilter.filterWhereField(field, isGreaterThan = constraint.safeValue)
287287
is WhereConstraint.LessThanOrEqualTo -> FIRFilter.filterWhereField(field, isLessThanOrEqualTo = constraint.safeValue)
@@ -292,8 +292,8 @@ actual open class Query(open val ios: FIRQuery) {
292292
is WhereConstraint.NotInArray -> FIRFilter.filterWhereField(field, notIn = constraint.safeValues)
293293
}
294294
is Filter.Path -> when (constraint) {
295-
is WhereConstraint.EqualTo -> FIRFilter.filterWhereFieldPath(path.ios, isEqualTo = constraint.safeValue ?: NSNull)
296-
is WhereConstraint.NotEqualTo -> FIRFilter.filterWhereFieldPath(path.ios, isNotEqualTo = constraint.safeValue ?: NSNull)
295+
is WhereConstraint.EqualTo -> FIRFilter.filterWhereFieldPath(path.ios, isEqualTo = constraint.safeValue ?: NSNull.`null`())
296+
is WhereConstraint.NotEqualTo -> FIRFilter.filterWhereFieldPath(path.ios, isNotEqualTo = constraint.safeValue ?: NSNull.`null`())
297297
is WhereConstraint.LessThan -> FIRFilter.filterWhereFieldPath(path.ios, isLessThan = constraint.safeValue)
298298
is WhereConstraint.GreaterThan -> FIRFilter.filterWhereFieldPath(path.ios, isGreaterThan = constraint.safeValue)
299299
is WhereConstraint.LessThanOrEqualTo -> FIRFilter.filterWhereFieldPath(path.ios, isLessThanOrEqualTo = constraint.safeValue)

0 commit comments

Comments
 (0)