@@ -18,6 +18,7 @@ import kotlinx.coroutines.flow.filter
1818import kotlinx.coroutines.flow.first
1919import kotlinx.coroutines.test.TestResult
2020import kotlinx.coroutines.withContext
21+ import kotlinx.serialization.KSerializer
2122import kotlinx.serialization.Serializable
2223import kotlinx.serialization.builtins.nullable
2324import 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 }
0 commit comments