Skip to content

Commit caae6e9

Browse files
authored
Merge pull request #60 from FrangSierra/development
Development
2 parents 5883a9d + 7badcb4 commit caae6e9

File tree

7 files changed

+464
-121
lines changed

7 files changed

+464
-121
lines changed

app/build.gradle

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ buildscript {
22
ext {
33
rx_version = "2.1.10"
44
rx_android_version = "2.0.2"
5-
firebase_auth_version='15.1.0'
6-
firebase_database_version='15.0.0'
7-
firebase_storage_version='15.0.2'
8-
firebase_firestore_version='16.0.0'
5+
firebase_auth_version='16.0.2'
6+
firebase_database_version='16.0.1'
7+
firebase_storage_version='16.0.1'
8+
firebase_firestore_version='17.0.2'
99
support_version = "27.0.2"
1010
}
1111
}
@@ -20,7 +20,7 @@ android {
2020
}
2121

2222
compileSdkVersion 27
23-
buildToolsVersion "26.0.3"
23+
buildToolsVersion "27.0.3"
2424

2525
defaultConfig {
2626
minSdkVersion 14
@@ -32,18 +32,23 @@ android {
3232
}
3333

3434
repositories{
35-
maven { url 'https://maven.google.com' }
35+
google()
3636
}
3737

3838
dependencies {
39-
compile fileTree(dir: 'libs', include: ['*.jar'])
40-
provided "com.google.firebase:firebase-auth:$firebase_auth_version"
41-
provided "com.google.firebase:firebase-database:$firebase_database_version"
42-
provided "com.google.firebase:firebase-storage:$firebase_storage_version"
43-
provided "com.google.firebase:firebase-firestore:$firebase_firestore_version"
44-
provided "com.android.support:recyclerview-v7:$support_version"
45-
compile "io.reactivex.rxjava2:rxjava:$rx_version"
46-
compile "io.reactivex.rxjava2:rxandroid:$rx_android_version"
47-
testCompile 'junit:junit:4.12'
48-
testCompile "org.mockito:mockito-core:2.2.16"
39+
implementation fileTree(dir: 'libs', include: ['*.jar'])
40+
compileOnly "com.google.firebase:firebase-auth:$firebase_auth_version"
41+
compileOnly "com.google.firebase:firebase-database:$firebase_database_version"
42+
compileOnly "com.google.firebase:firebase-storage:$firebase_storage_version"
43+
compileOnly "com.google.firebase:firebase-firestore:$firebase_firestore_version"
44+
compileOnly "com.android.support:recyclerview-v7:$support_version"
45+
implementation "io.reactivex.rxjava2:rxjava:$rx_version"
46+
implementation "io.reactivex.rxjava2:rxandroid:$rx_android_version"
47+
48+
testImplementation "com.google.firebase:firebase-auth:$firebase_auth_version"
49+
testImplementation "com.google.firebase:firebase-database:$firebase_database_version"
50+
testImplementation "com.google.firebase:firebase-storage:$firebase_storage_version"
51+
testImplementation "com.google.firebase:firebase-firestore:$firebase_firestore_version"
52+
testImplementation 'junit:junit:4.12'
53+
testImplementation "org.mockito:mockito-core:2.2.16"
4954
}

app/src/main/java/durdinapps/rxfirebase2/RxFirestore.java

Lines changed: 274 additions & 100 deletions
Large diffs are not rendered by default.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package durdinapps.rxfirebase2;
2+
3+
import android.support.annotation.Nullable;
4+
5+
import com.google.firebase.firestore.DocumentReference;
6+
import com.google.firebase.firestore.DocumentSnapshot;
7+
import com.google.firebase.firestore.EventListener;
8+
import com.google.firebase.firestore.FirebaseFirestoreException;
9+
import com.google.firebase.firestore.ListenerRegistration;
10+
11+
import io.reactivex.Completable;
12+
import io.reactivex.CompletableEmitter;
13+
import io.reactivex.CompletableOnSubscribe;
14+
import io.reactivex.functions.Cancellable;
15+
16+
public class RxFirestoreOfflineHandler {
17+
18+
/**
19+
* Method that listen a given reference and waits for a single change inside of it. However, this method
20+
* is just called in offline methods of add/set/delete in a new reference. That's why this reference should be
21+
* updated just once after successfully modify the reference with an offline operation.
22+
*
23+
* @param ref Document reference to be listened.
24+
* @return A Completable which emits when the given reference receives an offline update.
25+
*/
26+
public static Completable listenOfflineListener(final DocumentReference ref) {
27+
return Completable.create(new CompletableOnSubscribe() {
28+
@Override
29+
public void subscribe(final CompletableEmitter emitter) {
30+
try {
31+
final ListenerRegistration listener = ref.addSnapshotListener(new EventListener<DocumentSnapshot>() {
32+
@Override
33+
public void onEvent(@Nullable DocumentSnapshot documentSnapshot, @Nullable FirebaseFirestoreException e) {
34+
if (e != null) {
35+
emitter.onError(e);
36+
} else {
37+
if (documentSnapshot != null) {
38+
emitter.onComplete();
39+
} else {
40+
emitter.onError(new NullPointerException("Empty Snapshot"));
41+
}
42+
}
43+
}
44+
});
45+
46+
emitter.setCancellable(new Cancellable() {
47+
@Override
48+
public void cancel() {
49+
listener.remove();
50+
}
51+
});
52+
} catch (Exception e) {
53+
emitter.onError(e);
54+
}
55+
}
56+
});
57+
}
58+
}

app/src/test/java/durdinapps/rxfirebase2/RxFirestoreTest.java

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import com.google.firebase.firestore.CollectionReference;
55
import com.google.firebase.firestore.DocumentReference;
66
import com.google.firebase.firestore.DocumentSnapshot;
7+
import com.google.firebase.firestore.ListenerRegistration;
78
import com.google.firebase.firestore.Query;
8-
import com.google.firebase.firestore.QueryDocumentSnapshot;
99
import com.google.firebase.firestore.QuerySnapshot;
1010

1111
import org.junit.Before;
@@ -17,12 +17,16 @@
1717

1818
import java.util.ArrayList;
1919
import java.util.Collections;
20+
import java.util.HashMap;
2021
import java.util.Iterator;
2122
import java.util.List;
2223

2324
import io.reactivex.observers.TestObserver;
2425

26+
import static durdinapps.rxfirebase2.RxTestUtil.eventSnapshotListener;
27+
import static durdinapps.rxfirebase2.RxTestUtil.setupOfflineTask;
2528
import static durdinapps.rxfirebase2.RxTestUtil.setupTask;
29+
import static durdinapps.rxfirebase2.RxTestUtil.testOnCompleteListener;
2630
import static durdinapps.rxfirebase2.RxTestUtil.testOnSuccessListener;
2731
import static org.mockito.Mockito.verify;
2832
import static org.mockito.Mockito.when;
@@ -71,13 +75,21 @@ public class RxFirestoreTest {
7175
@Mock
7276
private Task<DocumentSnapshot> documentSnapshotTask;
7377

78+
@Mock
79+
private Task<DocumentReference> documentRefTask;
80+
7481
@Mock
7582
private Task<QuerySnapshot> queryResultTask;
7683

7784
@Mock
7885
private Task<QuerySnapshot> emptyQueryResultTask;
7986

87+
@Mock
88+
private ListenerRegistration registration;
89+
8090

91+
private HashMap<String, Object> updateMap = new HashMap<>();
92+
private ChildDocData setData = new ChildDocData();
8193
private ChildDocData childData = new ChildDocData();
8294
private List<ChildDocData> childDataList = new ArrayList<>();
8395

@@ -90,13 +102,17 @@ public void setup() {
90102
setupTask(queryResultTask);
91103
setupTask(emptyQueryResultTask);
92104
setupTask(mockVoidTask);
105+
setupOfflineTask(documentReference, registration);
93106

94107
when(documentReference.get()).thenReturn(documentSnapshotTask);
95108
when(emptyDocumentReference.get()).thenReturn(emptyDocumentSnapshotTask);
96109
when(collectionReference.get()).thenReturn(queryResultTask);
97110
when(emptyCollectionReference.get()).thenReturn(emptyQueryResultTask);
98111
when(queryReference.get()).thenReturn(queryResultTask);
99112
when(emptyQueryReference.get()).thenReturn(emptyQueryResultTask);
113+
when(documentReference.delete()).thenReturn(mockVoidTask);
114+
when(documentReference.update(updateMap)).thenReturn(mockVoidTask);
115+
when(collectionReference.add(setData)).thenReturn(documentRefTask);
100116
when(documentSnapshot.toObject(ChildDocData.class)).thenReturn(childData);
101117
when(documentSnapshot.exists()).thenReturn(true); //This snapshots exist
102118
when(documentSnapshot.exists()).thenReturn(true); //This snapshots exist
@@ -308,6 +324,85 @@ public void testMappedGetEmptyQuery() throws InterruptedException {
308324
.assertComplete();
309325
}
310326

327+
@Test
328+
public void testSetDocumentOffline() throws InterruptedException {
329+
TestObserver<Void> testObserver = RxFirestore
330+
.setDocumentOffline(documentReference, setData)
331+
.test();
332+
333+
eventSnapshotListener.getValue().onEvent(documentSnapshot, null);
334+
335+
verify(documentReference).set(setData);
336+
337+
testObserver
338+
.assertNoErrors()
339+
.assertComplete();
340+
}
341+
342+
@Test
343+
public void testUpdateDocument() throws InterruptedException {
344+
345+
TestObserver<Void> storageTestObserver =
346+
RxFirestore.updateDocument(documentReference, updateMap)
347+
.test();
348+
349+
testOnCompleteListener.getValue().onComplete(mockVoidTask);
350+
351+
verify(documentReference).update(updateMap);
352+
353+
storageTestObserver.assertNoErrors()
354+
.assertComplete()
355+
.dispose();
356+
}
357+
358+
359+
@Test
360+
public void testUpdateDocumentOffline() throws InterruptedException {
361+
TestObserver<Void> testObserver = RxFirestore
362+
.updateDocumentOffline(documentReference, updateMap)
363+
.test();
364+
365+
eventSnapshotListener.getValue().onEvent(documentSnapshot, null);
366+
367+
verify(documentReference).update(updateMap);
368+
369+
testObserver
370+
.assertNoErrors()
371+
.assertComplete();
372+
}
373+
374+
375+
@Test
376+
public void testDeleteDocument() throws InterruptedException {
377+
378+
TestObserver<Void> storageTestObserver =
379+
RxFirestore.deleteDocument(documentReference)
380+
.test();
381+
382+
testOnCompleteListener.getValue().onComplete(mockVoidTask);
383+
384+
verify(documentReference).delete();
385+
386+
storageTestObserver.assertNoErrors()
387+
.assertComplete()
388+
.dispose();
389+
}
390+
391+
@Test
392+
public void testDeleteDocumentOffline() throws InterruptedException {
393+
TestObserver<Void> testObserver = RxFirestore
394+
.deleteDocumentOffline(documentReference)
395+
.test();
396+
397+
eventSnapshotListener.getValue().onEvent(documentSnapshot, null);
398+
verify(documentReference).delete();
399+
400+
testObserver
401+
.assertNoErrors()
402+
.assertComplete();
403+
}
404+
405+
311406
class ChildDocData {
312407
int id;
313408
String str;

app/src/test/java/durdinapps/rxfirebase2/RxTestUtil.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
import com.google.android.gms.tasks.OnFailureListener;
55
import com.google.android.gms.tasks.OnSuccessListener;
66
import com.google.android.gms.tasks.Task;
7+
import com.google.firebase.firestore.DocumentReference;
8+
import com.google.firebase.firestore.DocumentSnapshot;
9+
import com.google.firebase.firestore.EventListener;
10+
import com.google.firebase.firestore.ListenerRegistration;
711

812
import org.mockito.ArgumentCaptor;
913

@@ -25,10 +29,16 @@ public class RxTestUtil {
2529
public static ArgumentCaptor<OnCompleteListener> testOnCompleteListener = ArgumentCaptor.forClass(OnCompleteListener.class);
2630
public static ArgumentCaptor<OnSuccessListener> testOnSuccessListener = ArgumentCaptor.forClass(OnSuccessListener.class);
2731
public static ArgumentCaptor<OnFailureListener> testOnFailureListener = ArgumentCaptor.forClass(OnFailureListener.class);
32+
public static ArgumentCaptor<EventListener<DocumentSnapshot>> eventSnapshotListener = ArgumentCaptor.forClass(EventListener.class);
2833

2934
public static <T> void setupTask(Task<T> task) {
3035
when(task.addOnCompleteListener(testOnCompleteListener.capture())).thenReturn(task);
3136
when(task.addOnSuccessListener(testOnSuccessListener.capture())).thenReturn(task);
3237
when(task.addOnFailureListener(testOnFailureListener.capture())).thenReturn(task);
3338
}
39+
40+
41+
public static void setupOfflineTask(DocumentReference documentReference, ListenerRegistration registration) {
42+
when(documentReference.addSnapshotListener(eventSnapshotListener.capture())).thenReturn(registration);
43+
}
3444
}

build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
buildscript {
44
repositories {
55
jcenter()
6+
google()
67
}
78
dependencies {
8-
classpath 'com.android.tools.build:gradle:2.3.0'
9+
classpath 'com.android.tools.build:gradle:3.1.2'
910
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
1011
// NOTE: Do not place your application dependencies here; they belong
1112
// in the individual module build.gradle files
@@ -14,8 +15,8 @@ buildscript {
1415

1516
allprojects {
1617
repositories {
18+
google()
1719
jcenter()
18-
maven { url 'https://maven.google.com' }
1920
}
2021
}
2122

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Tue Sep 19 19:36:52 CEST 2017
1+
#Thu Jul 12 10:29:40 CEST 2018
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

0 commit comments

Comments
 (0)