getHttpsCallable(@NonNull final FirebaseFunctions functions,
60 | @NonNull final String name) {
61 | return getHttpsCallable(functions, name, null);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/durdinapps/rxfirebase2/RxFirebaseRemote.java:
--------------------------------------------------------------------------------
1 | package durdinapps.rxfirebase2;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import com.google.firebase.remoteconfig.FirebaseRemoteConfig;
6 |
7 | import io.reactivex.Completable;
8 | import io.reactivex.CompletableEmitter;
9 | import io.reactivex.CompletableOnSubscribe;
10 |
11 | public class RxFirebaseRemote {
12 |
13 | /**
14 | * Fetches parameter values for your app.
15 | * Configuration values may be served from the Default Config (local cache) or from the Remote Config Server,
16 | * depending on how much time has elapsed since parameter values were last fetched from the Remote Config server.
17 | * This method lets the caller specify the cache expiration in seconds.
18 | *
19 | * To identify the current app instance, the fetch request creates a Firebase Instance ID token,
20 | * which periodically sends data to the Firebase backend. To stop the periodic sync, call deleteInstanceId();
21 | * calling fetchConfig again creates a new token and resumes the periodic sync.
22 | *
23 | * @param config firebase remote config instance.
24 | * @param cacheLifeTime If the data in the cache was fetched no longer than this many seconds ago, this method will return the cached data.
25 | * If not, a fetch from the Remote Config Server will be attempted.
26 | * @return a {@link Completable} which emits when the action is completed.
27 | */
28 | @NonNull
29 | public static Completable fetch(@NonNull final FirebaseRemoteConfig config,
30 | @NonNull final long cacheLifeTime) {
31 | return Completable.create(new CompletableOnSubscribe() {
32 | @Override
33 | public void subscribe(CompletableEmitter emitter) {
34 | RxCompletableHandler.assignOnTask(emitter, config.fetch(cacheLifeTime));
35 | }
36 | });
37 | }
38 |
39 | /**
40 | * Fetches parameter values for your app.
41 | * Configuration values may be served from the Default Config (local cache) or from the Remote Config Server,
42 | * depending on how much time has elapsed since parameter values were last fetched from the Remote Config server.
43 | * This method lets the caller specify the cache expiration in seconds.
44 | *
45 | * To identify the current app instance, the fetch request creates a Firebase Instance ID token,
46 | * which periodically sends data to the Firebase backend. To stop the periodic sync, call deleteInstanceId();
47 | * calling fetchConfig again creates a new token and resumes the periodic sync.
48 | *
49 | * @param config firebase remote config instance.
50 | * @return a {@link Completable} which emits when the action is completed.
51 | */
52 | @NonNull
53 | public static Completable fetch(@NonNull final FirebaseRemoteConfig config) {
54 | return Completable.create(new CompletableOnSubscribe() {
55 | @Override
56 | public void subscribe(CompletableEmitter emitter) {
57 | RxCompletableHandler.assignOnTask(emitter, config.fetch(43200L));
58 | }
59 | });
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/durdinapps/rxfirebase2/DocumentSnapshotMapper.java:
--------------------------------------------------------------------------------
1 | package durdinapps.rxfirebase2;
2 |
3 |
4 | import com.google.firebase.firestore.DocumentSnapshot;
5 | import com.google.firebase.firestore.QuerySnapshot;
6 |
7 | import java.util.ArrayList;
8 | import java.util.LinkedHashMap;
9 | import java.util.List;
10 |
11 | import androidx.annotation.NonNull;
12 | import io.reactivex.functions.Function;
13 | import io.reactivex.functions.Predicate;
14 |
15 | public abstract class DocumentSnapshotMapper implements Function {
16 |
17 | private DocumentSnapshotMapper() {
18 | }
19 |
20 | public static DocumentSnapshotMapper of(Class clazz) {
21 | return new TypedDocumentSnapshotMapper(clazz);
22 | }
23 |
24 | public static DocumentSnapshotMapper> listOf(Class clazz) {
25 | return new TypedListQuerySnapshotMapper<>(clazz);
26 | }
27 |
28 | public static DocumentSnapshotMapper> listOf(Class clazz, Function mapper) {
29 | return new TypedListQuerySnapshotMapper<>(clazz, mapper);
30 | }
31 |
32 | public static TypedMapQuerySnapshotMapper mapOf(Class clazz) {
33 | return new TypedMapQuerySnapshotMapper<>(clazz);
34 | }
35 |
36 | private static U getDataSnapshotTypedValue(DocumentSnapshot documentSnapshot, Class clazz) {
37 | return documentSnapshot.toObject(clazz);
38 | }
39 |
40 | private static class TypedDocumentSnapshotMapper extends DocumentSnapshotMapper {
41 |
42 | private final Class clazz;
43 |
44 | public TypedDocumentSnapshotMapper(final Class clazz) {
45 | this.clazz = clazz;
46 | }
47 |
48 | @Override
49 | public U apply(final DocumentSnapshot documentSnapshot) {
50 | return getDataSnapshotTypedValue(documentSnapshot, clazz);
51 | }
52 | }
53 |
54 | private static class TypedListQuerySnapshotMapper extends DocumentSnapshotMapper> {
55 |
56 | private final Class clazz;
57 | private final Function mapper;
58 |
59 | TypedListQuerySnapshotMapper(final Class clazz) {
60 | this(clazz, null);
61 | }
62 |
63 | TypedListQuerySnapshotMapper(final Class clazz, Function mapper) {
64 | this.clazz = clazz;
65 | this.mapper = mapper;
66 | }
67 |
68 | @Override
69 | public List apply(final QuerySnapshot querySnapshot) throws Exception {
70 | List items = new ArrayList<>();
71 | for (DocumentSnapshot documentSnapshot : querySnapshot) {
72 | items.add(mapper != null
73 | ? mapper.apply(documentSnapshot)
74 | : getDataSnapshotTypedValue(documentSnapshot, clazz));
75 | }
76 | return items;
77 | }
78 | }
79 |
80 |
81 | private static class TypedMapQuerySnapshotMapper extends DocumentSnapshotMapper> {
82 |
83 | private final Class clazz;
84 |
85 | TypedMapQuerySnapshotMapper(final Class clazz) {
86 | this.clazz = clazz;
87 | }
88 |
89 | @Override
90 | public LinkedHashMap apply(final QuerySnapshot querySnapshot) {
91 | LinkedHashMap items = new LinkedHashMap<>();
92 | for (DocumentSnapshot documentSnapshot : querySnapshot) {
93 | items.put(documentSnapshot.getId(), getDataSnapshotTypedValue(documentSnapshot, clazz));
94 | }
95 | return items;
96 | }
97 | }
98 |
99 | static final Predicate QUERY_EXISTENCE_PREDICATE = new Predicate() {
100 | @Override
101 | public boolean test(@NonNull QuerySnapshot querySnapshot) throws Exception {
102 | return !querySnapshot.isEmpty();
103 | }
104 | };
105 |
106 | static final Predicate DOCUMENT_EXISTENCE_PREDICATE = new Predicate() {
107 | @Override
108 | public boolean test(@NonNull DocumentSnapshot documentSnapshot) throws Exception {
109 | return documentSnapshot.exists();
110 | }
111 | };
112 | }
113 |
--------------------------------------------------------------------------------
/app/src/main/java/durdinapps/rxfirebase2/RxFirebaseQuery.java:
--------------------------------------------------------------------------------
1 | package durdinapps.rxfirebase2;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import com.google.firebase.database.DataSnapshot;
6 | import com.google.firebase.database.DatabaseReference;
7 | import com.google.firebase.database.Query;
8 |
9 | import java.util.List;
10 |
11 | import io.reactivex.Flowable;
12 | import io.reactivex.Maybe;
13 | import io.reactivex.Single;
14 | import io.reactivex.functions.Function;
15 |
16 | import static durdinapps.rxfirebase2.RxFirebaseDatabase.observeMultipleSingleValueEvent;
17 | import static durdinapps.rxfirebase2.RxFirebaseDatabase.observeSingleValueEvent;
18 | import static durdinapps.rxfirebase2.RxFirebaseDatabase.requestFilteredReferenceKeys;
19 |
20 | /**
21 | * Basic builder to create Firebase queries based on filters from different {@link DatabaseReference references}.
22 | */
23 | public class RxFirebaseQuery {
24 | private Maybe whereMaybe;
25 |
26 | private RxFirebaseQuery() {
27 | }
28 |
29 | /**
30 | * Retrieve a new instance for {@link RxFirebaseQuery}.
31 | */
32 | public static RxFirebaseQuery getInstance() {
33 | return new RxFirebaseQuery();
34 | }
35 |
36 |
37 | /**
38 | * Generate a filter based on the method {@link RxFirebaseDatabase#requestFilteredReferenceKeys(DatabaseReference, Query)}.
39 | *
40 | * @param from base reference where you want to retrieve the original references.
41 | * @param whereRef reference that you use as a filter to create your from references.
42 | * @return the current instance of {@link RxFirebaseQuery}.
43 | */
44 | @NonNull
45 | public RxFirebaseQuery filterByRefs(@NonNull DatabaseReference from,
46 | @NonNull Query whereRef) {
47 | whereMaybe = requestFilteredReferenceKeys(from, whereRef);
48 | return this;
49 | }
50 |
51 | /**
52 | * Generate a filter based on a given function.
53 | *
54 | * @param whereRef reference that you use as a filter to create your from references.
55 | * @param mapper Custom mapper to map the retrieved where references to new {@link DatabaseReference}.
56 | * @return the current instance of {@link RxFirebaseQuery}.
57 | */
58 | @NonNull
59 | public RxFirebaseQuery filter(@NonNull Query whereRef,
60 | @NonNull final Function super DataSnapshot, ? extends DatabaseReference[]> mapper) {
61 | whereMaybe = observeSingleValueEvent(whereRef, mapper);
62 | return this;
63 | }
64 |
65 | /**
66 | * Retrieve the final result as a {@link Single} which emmit the final result of the event as a {@link List} of {@link DataSnapshot}.
67 | */
68 | @NonNull
69 | public Single> asList() {
70 | return create().toList();
71 | }
72 |
73 | /**
74 | * Retrieve the final result as a {@link Single} which emmit the final result of the event as a {@link List} of a given type.
75 | *
76 | * @param mapper specific function to map the dispatched events.
77 | */
78 | @NonNull
79 | public Single> asList(@NonNull final Function super List, ? extends List> mapper) {
80 | return create().toList().map(mapper);
81 | }
82 |
83 | /**
84 | * Retrieve the final result of the query as a {@link Flowable} which emmit mapped values.
85 | *
86 | * @param mapper specific function to map the dispatched events.
87 | */
88 | @NonNull
89 | public Flowable create(@NonNull final Function super DataSnapshot, ? extends T> mapper) {
90 | return create().map(mapper);
91 | }
92 |
93 | /**
94 | * Retrieve the final result of the query as a {@link Flowable} which emmit {@link DataSnapshot}.
95 | */
96 | @NonNull
97 | public Flowable create() {
98 | if (whereMaybe == null)
99 | throw new IllegalArgumentException("It's necessary define a where function to retrieve data");
100 |
101 | return whereMaybe.toFlowable().flatMap(new Function>() {
102 | @Override
103 | public Flowable apply(@io.reactivex.annotations.NonNull DatabaseReference[] keys) throws Exception {
104 | return observeMultipleSingleValueEvent(keys);
105 | }
106 | });
107 | }
108 | }
109 |
110 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/java/durdinapps/rxfirebase2/DataSnapshotMapper.java:
--------------------------------------------------------------------------------
1 | package durdinapps.rxfirebase2;
2 |
3 | import com.google.firebase.database.DataSnapshot;
4 | import com.google.firebase.database.GenericTypeIndicator;
5 |
6 | import java.util.ArrayList;
7 | import java.util.LinkedHashMap;
8 | import java.util.List;
9 |
10 | import androidx.annotation.NonNull;
11 | import durdinapps.rxfirebase2.exceptions.RxFirebaseDataCastException;
12 | import io.reactivex.exceptions.Exceptions;
13 | import io.reactivex.functions.Function;
14 | import io.reactivex.functions.Predicate;
15 |
16 | public abstract class DataSnapshotMapper implements Function {
17 |
18 | private DataSnapshotMapper() {
19 | }
20 |
21 | public static DataSnapshotMapper of(Class clazz) {
22 | return new TypedDataSnapshotMapper(clazz);
23 | }
24 |
25 | public static DataSnapshotMapper> listOf(Class clazz) {
26 | return new TypedListDataSnapshotMapper<>(clazz);
27 | }
28 |
29 | public static DataSnapshotMapper> listOf(Class clazz, Function mapper) {
30 | return new TypedListDataSnapshotMapper<>(clazz, mapper);
31 | }
32 |
33 | public static DataSnapshotMapper> mapOf(Class clazz) {
34 | return new TypedMapDataSnapshotMapper<>(clazz);
35 | }
36 |
37 | public static DataSnapshotMapper of(GenericTypeIndicator genericTypeIndicator) {
38 | return new GenericTypedDataSnapshotMapper(genericTypeIndicator);
39 | }
40 |
41 | public static DataSnapshotMapper, RxFirebaseChildEvent> ofChildEvent(Class clazz) {
42 | return new ChildEventDataSnapshotMapper(clazz);
43 | }
44 |
45 | private static U getDataSnapshotTypedValue(DataSnapshot dataSnapshot, Class clazz) {
46 | U value;
47 | try {
48 | value = dataSnapshot.getValue(clazz);
49 | } catch (Exception ex) {
50 | throw Exceptions.propagate(new RxFirebaseDataCastException(
51 | "There was a problem trying to cast " + dataSnapshot.toString() + " to " + clazz.getSimpleName(), ex));
52 | }
53 | if (value == null) {
54 | throw Exceptions.propagate(new RxFirebaseDataCastException(
55 | "The value after cast " + dataSnapshot.toString() + " to " + clazz.getSimpleName() + "is null."));
56 | }
57 | return value;
58 | }
59 |
60 | private static class TypedDataSnapshotMapper extends DataSnapshotMapper {
61 |
62 | private final Class clazz;
63 |
64 | public TypedDataSnapshotMapper(final Class clazz) {
65 | this.clazz = clazz;
66 | }
67 |
68 | @Override
69 | public U apply(final DataSnapshot dataSnapshot) {
70 | return getDataSnapshotTypedValue(dataSnapshot, clazz);
71 | }
72 | }
73 |
74 | private static class TypedListDataSnapshotMapper extends DataSnapshotMapper> {
75 |
76 | private final Class clazz;
77 | private final Function mapper;
78 |
79 | TypedListDataSnapshotMapper(final Class clazz) {
80 | this(clazz, null);
81 | }
82 |
83 | TypedListDataSnapshotMapper(final Class clazz, Function mapper) {
84 | this.clazz = clazz;
85 | this.mapper = mapper;
86 | }
87 |
88 | @Override
89 | public List apply(final DataSnapshot dataSnapshot) throws Exception {
90 | List items = new ArrayList<>();
91 | for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
92 | items.add(mapper != null
93 | ? mapper.apply(childSnapshot)
94 | : getDataSnapshotTypedValue(childSnapshot, clazz));
95 | }
96 | return items;
97 | }
98 | }
99 |
100 | private static class TypedMapDataSnapshotMapper extends DataSnapshotMapper> {
101 |
102 | private final Class clazz;
103 |
104 | TypedMapDataSnapshotMapper(final Class clazz) {
105 | this.clazz = clazz;
106 | }
107 |
108 | @Override
109 | public LinkedHashMap apply(final DataSnapshot dataSnapshot) {
110 | LinkedHashMap items = new LinkedHashMap<>();
111 | for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
112 | items.put(childSnapshot.getKey(), getDataSnapshotTypedValue(childSnapshot, clazz));
113 | }
114 | return items;
115 | }
116 | }
117 |
118 | private static class GenericTypedDataSnapshotMapper extends DataSnapshotMapper {
119 |
120 | private final GenericTypeIndicator genericTypeIndicator;
121 |
122 | public GenericTypedDataSnapshotMapper(GenericTypeIndicator genericTypeIndicator) {
123 | this.genericTypeIndicator = genericTypeIndicator;
124 | }
125 |
126 | @Override
127 | public U apply(DataSnapshot dataSnapshot) {
128 | U value = dataSnapshot.getValue(genericTypeIndicator);
129 | if (value == null) {
130 | throw Exceptions.propagate(new RxFirebaseDataCastException(
131 | "unable to cast firebase data response to generic type"));
132 | }
133 | return value;
134 | }
135 | }
136 |
137 | private static class ChildEventDataSnapshotMapper
138 | extends DataSnapshotMapper, RxFirebaseChildEvent> {
139 |
140 | private final Class clazz;
141 |
142 | public ChildEventDataSnapshotMapper(final Class clazz) {
143 | this.clazz = clazz;
144 | }
145 |
146 | @Override
147 | public RxFirebaseChildEvent apply(final RxFirebaseChildEvent rxFirebaseChildEvent) {
148 | DataSnapshot dataSnapshot = rxFirebaseChildEvent.getValue();
149 | if (dataSnapshot.exists()) {
150 | return new RxFirebaseChildEvent(
151 | dataSnapshot.getKey(),
152 | getDataSnapshotTypedValue(dataSnapshot, clazz),
153 | rxFirebaseChildEvent.getPreviousChildName(),
154 | rxFirebaseChildEvent.getEventType());
155 | } else {
156 | throw Exceptions.propagate(new RuntimeException("child dataSnapshot doesn't exist"));
157 | }
158 | }
159 | }
160 |
161 | static final Predicate DATA_SNAPSHOT_EXISTENCE_PREDICATE = new Predicate() {
162 | @Override
163 | public boolean test(@NonNull DataSnapshot dataSnapshot) throws Exception {
164 | return dataSnapshot.exists();
165 | }
166 | };
167 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Rx2Firebase
2 | [Rxjava 2.0](https://github.com/ReactiveX/RxJava/tree/2.x) wrapper on Google's [Android Firebase](https://firebase.google.com/docs/android/setup?hl=es) library.
3 |
4 | This repository started as a personal usage of [Nick Moskalenko](https://github.com/nmoskalenko) RxFirebase library. You can check his work [here](https://github.com/nmoskalenko/RxFirebase).
5 |
6 |
7 | ## Download
8 |
9 | ##### Gradle:
10 |
11 | ```groovy
12 | dependencies {
13 | compile 'com.github.FrangSierra:RxFirebase:1.5.6'
14 | }
15 | ```
16 | ```
17 | allprojects {
18 | repositories {
19 | ...
20 | maven { url "https://jitpack.io" }
21 | }
22 | }
23 | ```
24 |
25 | ## Usage
26 | Library provides set of static methods of classes:
27 | * RxFirebaseAuth
28 | * RxFirebaseUser
29 | * RxFirebaseDatabase
30 | * RxFirebaseStorage
31 | * RxFirestore
32 | * RxFirebaseFunctions
33 |
34 | ### Authentication:
35 | Sign in with email and password:
36 |
37 | ```java
38 | RxFirebaseAuth.signInWithEmailAndPassword(auth, email, password)
39 | .map(authResult -> authResult.getUser() != null)
40 | .take(1)
41 | .subscribe(logged -> {
42 | Log.i("Rxfirebase2", "User logged " + logged);
43 | });
44 | ```
45 | ### Firestore:
46 |
47 | You can observe values providing the Class of expected data like:
48 |
49 | ```java
50 | DocumentReference document = firestore.collection("Users").document("UserId_1");
51 | RxFirestore.observeDocumentRef(document)
52 | .subscribe( userDoc -> {
53 | //Do something with my snapshot
54 | });
55 | ```
56 |
57 | Get and set documents on a specific reference:
58 |
59 | ```java
60 | DocumentReference document = firestore.collection("Users").document("UserId_1");
61 | User mynewUser = User("newUserName", 24);
62 | //Set data
63 | RxFirestore.setDocument(document, myNewUser).subscribe();
64 | //Get and map data
65 | RxFirestore.getDocument(document)
66 | .map( userDoc -> { return userDoc.toObject(User.class); })
67 | .subscribe( casterUser -> {
68 | //Do something with my already casted user
69 | });
70 | ```
71 |
72 | Finally you can do sync operations on the database using `runTransaction` and if you wanna realize multiple
73 | operations at once, you should use the method `atomicOperation` which wraps the `WriteBatch` related methods from Firestore.
74 |
75 | ### Database:
76 |
77 | You can observe values providing the Class of expected data like:
78 |
79 | ```java
80 | RxFirebaseDatabase.observeSingleValueEvent(getPostsRef().child("posts"), Post.class)
81 | .subscribe(post -> {
82 | //Do something with yourpost
83 | });
84 | ```
85 |
86 | or providing your own mapper between DataSnapshot and your data type:
87 |
88 | ```java
89 | RxFirebaseDatabase.observeSingleValueEvent(getPostsRef().child("posts"),
90 | dataSnapshot -> {
91 | // do your own mapping here
92 | return new Author();
93 | })
94 | .subscribe(author -> {
95 | // process author value
96 | });
97 | ```
98 |
99 | There are some pre-defined mappers to make things easier:
100 |
101 | ##### Observing list values
102 |
103 | ```java
104 | RxFirebaseDatabase.observeSingleValueEvent(getPostsRef().child("posts"), DataSnapshotMapper.listOf(PostComment.class))
105 | .subscribe(blogPost -> {
106 | // process postcomment list item
107 | });
108 | ```
109 |
110 | ##### Observing map values
111 |
112 | ```java
113 | RxFirebaseDatabase.observeSingleValueEvent(getPostsRef().child("posts"), DataSnapshotMapper.mapOf(PostComment.class))
114 | .subscribe(PostCommentAsMapItem -> {
115 | // process blogPost as key-value pair
116 | });
117 | ```
118 |
119 | ### Storage:
120 |
121 | Download file from Firebase storage
122 |
123 | ```java
124 | RxFirebaseStorage.getFile(getStorageRef(), targetFile)
125 | .subscribe(taskSnapshot -> {
126 | Log.i("RxFirebaseSample", "transferred: " + snapshot.getBytesTransferred() + " bytes");
127 | }, throwable -> {
128 | Log.e("RxFirebaseSample", throwable.toString());
129 | });
130 | ```
131 |
132 | or download file as bytes array
133 |
134 | ```java
135 | RxFirebaseStorage.getBytes(getStorageRef(), 1024 * 100)
136 | .subscribe(bytes -> {
137 | Log.i("RxFirebaseSample", "downloaded: " + new String(bytes));
138 | }, throwable -> {
139 | Log.e("RxFirebaseSample", throwable.toString());
140 | });
141 | ```
142 | ### RxFirebaseQuery
143 |
144 | RxFirebaseQuery is a builder class used to work together with methods from RxFirebaseDatabase that allow you to retrieve data from multiple databaseReferences. Doing this allow you to build and create dynamic queries to retrieve database objects from references retrieved from different tables easily.
145 | At the moment RxFirebaseQuery just allow the user to create the queries and retrieve the data. Filters should be done with the `DatabaseReference` items that you pass to the constructor. In other hand for update and delete data you should use `Firebase` method `updateChildren()`
146 | ```java
147 | DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
148 | DatabaseReference from = reference.child("tweets");
149 | Query where = reference.child("users").child(userId).child("feedReferences");
150 | RxFirebaseQuery.getInstance()
151 | .filterByRefs(from, where)
152 | .asList()
153 | .subscribe(dataSnapshots -> {
154 | Log.i("RxFirebase", "Retrieved a total of " + dataSnapshots.size() + " tweets");
155 | for (DataSnapshot dataSnapshot : dataSnapshots) {
156 | Tweet tweet = dataSnapshot.getValue(Tweet.class);
157 | Log.i("RxFirebase", "New tweet for user feed: " + tweet.getDescription());
158 | }
159 | });
160 |
161 | ## RxJava and RxJava 2.0
162 | One of the differences between RxJava and RxJava 2 is that RxJava 2 no longer accepts `null` values. Throwing a `NullPointerException` immediately. For this reason some of the methods of the library as been redesigned to return a `Completable` instead of a `Observable`. For example:
163 |
164 | #### RxFirebase
165 |
166 | ```java
167 | @NonNull
168 | public static Observable updateEmail(@NonNull final FirebaseUser firebaseUser, @NonNull final String email) {
169 | return Observable.create(new Observable.OnSubscribe() {
170 | @Override
171 | public void call(final Subscriber super Void> subscriber) {
172 | RxHandler.assignOnTask(subscriber, firebaseUser.updateEmail(email));
173 | }
174 | });
175 | }
176 | ```
177 |
178 | #### Rx2Firebase
179 |
180 | ```java
181 | @NonNull
182 | public static Completable updateEmail(@NonNull final FirebaseUser firebaseUser, @NonNull final String email) {
183 | return Completable.create(new CompletableOnSubscribe() {
184 | @Override
185 | public void subscribe(CompletableEmitter emitter) throws Exception {
186 | RxCompletableHandler.assignOnTask(emitter, firebaseUser.updateEmail(email));
187 | }
188 | });
189 | }
190 | ```
191 |
192 | `RxCompletableHandler` manages the CompletableEmitters in the same way that `RxHandler` manages the `Subscriber`.
193 | You can check all the differences between RxJava and RxJava 2.0 in the next [Link](https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0)
194 |
195 | ## License
196 |
197 | MIT License
198 |
199 | Copyright (c) 2016 Francisco García Sierra
200 |
201 | Permission is hereby granted, free of charge, to any person obtaining a
202 | copy of this software and associated documentation files (the "Software"),
203 | to deal in the Software without restriction, including without limitation
204 | the rights to use, copy, modify, merge, publish, distribute, sublicense,
205 | and/or sell copies of the Software, and to permit persons to whom the
206 | Software is furnished to do so, subject to the following conditions:
207 |
208 | The above copyright notice and this permission notice shall be included
209 | in all copies or substantial portions of the Software.
210 |
211 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
212 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
213 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
214 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
215 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
216 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
217 | OTHER DEALINGS IN THE SOFTWARE.
218 |
219 |
220 | ## Support on Beerpay
221 | Hey dude! Help me out for a couple of :beers:!
222 |
223 | [](https://beerpay.io/FrangSierra/RxFirebase) [](https://beerpay.io/FrangSierra/RxFirebase?focus=wish)
224 |
--------------------------------------------------------------------------------
/app/src/test/java/durdinapps/rxfirebase2/RxFirebaseUserTest.java:
--------------------------------------------------------------------------------
1 | package durdinapps.rxfirebase2;
2 |
3 | import com.google.android.gms.tasks.Task;
4 | import com.google.firebase.auth.AuthCredential;
5 | import com.google.firebase.auth.AuthResult;
6 | import com.google.firebase.auth.FirebaseUser;
7 | import com.google.firebase.auth.GetTokenResult;
8 | import com.google.firebase.auth.UserProfileChangeRequest;
9 |
10 | import org.junit.Before;
11 | import org.junit.Test;
12 | import org.mockito.Mock;
13 | import org.mockito.MockitoAnnotations;
14 |
15 | import java.util.Collections;
16 |
17 | import io.reactivex.observers.TestObserver;
18 |
19 | import static durdinapps.rxfirebase2.RxTestUtil.ANY_EMAIL;
20 | import static durdinapps.rxfirebase2.RxTestUtil.ANY_PASSWORD;
21 | import static durdinapps.rxfirebase2.RxTestUtil.EXCEPTION;
22 | import static durdinapps.rxfirebase2.RxTestUtil.setupTask;
23 | import static durdinapps.rxfirebase2.RxTestUtil.testOnCompleteListener;
24 | import static durdinapps.rxfirebase2.RxTestUtil.testOnFailureListener;
25 | import static durdinapps.rxfirebase2.RxTestUtil.testOnSuccessListener;
26 | import static org.mockito.Mockito.verify;
27 | import static org.mockito.Mockito.when;
28 |
29 | public class RxFirebaseUserTest {
30 |
31 | @Mock
32 | FirebaseUser firebaseUser;
33 |
34 | @Mock
35 | GetTokenResult getTokenResult;
36 |
37 | @Mock
38 | Task voidTask;
39 |
40 | @Mock
41 | Task getTokenResultTask;
42 |
43 | @Mock
44 | UserProfileChangeRequest userProfileChangeRequest;
45 |
46 | @Mock
47 | AuthCredential authCredential;
48 |
49 | @Mock
50 | Task authCredentialTask;
51 |
52 | @Mock
53 | AuthResult authResult;
54 |
55 | @Mock
56 | Task authResultTask;
57 |
58 | private boolean ANY_FORCE_REFRESH_VALUE = true;
59 |
60 |
61 | @Before
62 | public void setUp() {
63 | MockitoAnnotations.initMocks(this);
64 |
65 | setupTask(getTokenResultTask);
66 | setupTask(voidTask);
67 | setupTask(authResultTask);
68 | setupTask(authCredentialTask);
69 |
70 | when(firebaseUser.getIdToken(ANY_FORCE_REFRESH_VALUE)).thenReturn(getTokenResultTask);
71 | when(firebaseUser.updateEmail(ANY_EMAIL)).thenReturn(voidTask);
72 | when(firebaseUser.updatePassword(ANY_PASSWORD)).thenReturn(voidTask);
73 | when(firebaseUser.updateProfile(userProfileChangeRequest)).thenReturn(voidTask);
74 | when(firebaseUser.delete()).thenReturn(voidTask);
75 | when(firebaseUser.reauthenticate(authCredential)).thenReturn(voidTask);
76 | when(firebaseUser.reauthenticateAndRetrieveData(authCredential)).thenReturn(authResultTask);
77 | when(firebaseUser.linkWithCredential(authCredential)).thenReturn(authResultTask);
78 | }
79 |
80 | @Test
81 | public void getToken() {
82 | TestObserver userTestObserver = RxFirebaseUser.getIdToken(firebaseUser, ANY_FORCE_REFRESH_VALUE).test();
83 |
84 | testOnSuccessListener.getValue().onSuccess(getTokenResult);
85 | testOnCompleteListener.getValue().onComplete(getTokenResultTask);
86 |
87 | verify(firebaseUser).getIdToken(ANY_FORCE_REFRESH_VALUE);
88 |
89 | userTestObserver.assertComplete()
90 | .assertNoErrors()
91 | .assertValueCount(1)
92 | .dispose();
93 | }
94 |
95 | @Test
96 | public void getTokenError() {
97 | TestObserver userTestObserver = RxFirebaseUser.getIdToken(firebaseUser, ANY_FORCE_REFRESH_VALUE).test();
98 | testOnFailureListener.getValue().onFailure(EXCEPTION);
99 | verify(firebaseUser).getIdToken(ANY_FORCE_REFRESH_VALUE);
100 |
101 | userTestObserver.assertError(EXCEPTION)
102 | .dispose();
103 | }
104 |
105 | @Test
106 | public void updateEmail() {
107 | TestObserver userTestObserver = RxFirebaseUser.updateEmail(firebaseUser, ANY_EMAIL).test();
108 |
109 | testOnCompleteListener.getValue().onComplete(voidTask);
110 | testOnSuccessListener.getValue().onSuccess(voidTask);
111 |
112 | verify(firebaseUser).updateEmail(ANY_EMAIL);
113 |
114 | userTestObserver.assertComplete()
115 | .dispose();
116 |
117 | }
118 |
119 | @Test
120 | public void updateEmailError() {
121 | TestObserver userTestObserver = RxFirebaseUser.updateEmail(firebaseUser, ANY_EMAIL).test();
122 |
123 | testOnFailureListener.getValue().onFailure(EXCEPTION);
124 |
125 | verify(firebaseUser).updateEmail(ANY_EMAIL);
126 |
127 | userTestObserver.assertError(EXCEPTION)
128 | .dispose();
129 |
130 | }
131 |
132 | @Test
133 | public void updatePassword() {
134 | TestObserver userTestObserver = RxFirebaseUser.updatePassword(firebaseUser, ANY_PASSWORD).test();
135 | testOnCompleteListener.getValue().onComplete(voidTask);
136 | testOnSuccessListener.getValue().onSuccess(voidTask);
137 |
138 | verify(firebaseUser).updatePassword(ANY_PASSWORD);
139 |
140 | userTestObserver.assertComplete()
141 | .dispose();
142 | }
143 |
144 | @Test
145 | public void updatePasswordError() {
146 | TestObserver userTestObserver = RxFirebaseUser.updatePassword(firebaseUser, ANY_PASSWORD).test();
147 |
148 | testOnFailureListener.getValue().onFailure(EXCEPTION);
149 |
150 | verify(firebaseUser).updatePassword(ANY_PASSWORD);
151 |
152 | userTestObserver.assertError(EXCEPTION)
153 | .dispose();
154 |
155 | }
156 |
157 | @Test
158 | public void updateProfile() {
159 | TestObserver userTestObserver = RxFirebaseUser.updateProfile(firebaseUser, userProfileChangeRequest).test();
160 |
161 | testOnCompleteListener.getValue().onComplete(voidTask);
162 | testOnSuccessListener.getValue().onSuccess(voidTask);
163 |
164 | verify(firebaseUser).updateProfile(userProfileChangeRequest);
165 |
166 | userTestObserver.assertComplete()
167 | .dispose();
168 |
169 | }
170 |
171 | @Test
172 | public void updateProfileError() {
173 | TestObserver userTestObserver = RxFirebaseUser.updateProfile(firebaseUser, userProfileChangeRequest).test();
174 |
175 | testOnFailureListener.getValue().onFailure(EXCEPTION);
176 |
177 | verify(firebaseUser).updateProfile(userProfileChangeRequest);
178 |
179 | userTestObserver.assertError(EXCEPTION)
180 | .dispose();
181 |
182 | }
183 |
184 | @Test
185 | public void delete() {
186 | TestObserver userTestObserver = RxFirebaseUser.delete(firebaseUser).test();
187 |
188 | testOnCompleteListener.getValue().onComplete(voidTask);
189 | testOnSuccessListener.getValue().onSuccess(voidTask);
190 |
191 | verify(firebaseUser).delete();
192 |
193 | userTestObserver.assertComplete()
194 | .dispose();
195 | }
196 |
197 | @Test
198 | public void deleteError() {
199 | TestObserver userTestObserver = RxFirebaseUser.delete(firebaseUser).test();
200 |
201 | testOnFailureListener.getValue().onFailure(EXCEPTION);
202 | verify(firebaseUser).delete();
203 |
204 | userTestObserver.assertError(EXCEPTION)
205 | .dispose();
206 | }
207 |
208 | @Test
209 | public void reAuthenticate() {
210 | TestObserver userTestObserver = RxFirebaseUser.reAuthenticate(firebaseUser, authCredential).test();
211 |
212 | testOnCompleteListener.getValue().onComplete(voidTask);
213 | testOnSuccessListener.getValue().onSuccess(voidTask);
214 |
215 | verify(firebaseUser).reauthenticate(authCredential);
216 |
217 | userTestObserver.assertComplete()
218 | .dispose();
219 |
220 | }
221 |
222 | @Test
223 | public void reauthenticateAndRetrieveData() {
224 | TestObserver userTestObserver = RxFirebaseUser.reauthenticateAndRetrieveData(firebaseUser, authCredential).test();
225 |
226 | testOnSuccessListener.getValue().onSuccess(authResult);
227 | testOnCompleteListener.getValue().onComplete(authResultTask);
228 |
229 | verify(firebaseUser).reauthenticateAndRetrieveData(authCredential);
230 |
231 | userTestObserver.assertNoErrors()
232 | .assertValueCount(1)
233 | .assertComplete()
234 | .assertValueSet(Collections.singletonList(authResult))
235 | .dispose();
236 |
237 | }
238 |
239 | @Test
240 | public void reAuthenticateError() {
241 | TestObserver userTestObserver = RxFirebaseUser.reAuthenticate(firebaseUser, authCredential).test();
242 |
243 | testOnFailureListener.getValue().onFailure(EXCEPTION);
244 |
245 | verify(firebaseUser).reauthenticate(authCredential);
246 |
247 | userTestObserver.assertError(EXCEPTION)
248 | .dispose();
249 | }
250 |
251 | @Test
252 | public void linkWithCredentials() {
253 | TestObserver userTestObserver = RxFirebaseUser.linkWithCredential(firebaseUser, authCredential).test();
254 |
255 | testOnSuccessListener.getValue().onSuccess(authResult);
256 | testOnCompleteListener.getValue().onComplete(authResultTask);
257 |
258 | verify(firebaseUser).linkWithCredential(authCredential);
259 |
260 |
261 | userTestObserver.assertNoErrors()
262 | .assertValueCount(1)
263 | .assertComplete()
264 | .assertValueSet(Collections.singletonList(authResult))
265 | .dispose();
266 | }
267 |
268 | @Test
269 | public void linkWithCredentialsError() {
270 | TestObserver userTestObserver = RxFirebaseUser.linkWithCredential(firebaseUser, authCredential).test();
271 |
272 | testOnFailureListener.getValue().onFailure(EXCEPTION);
273 |
274 | verify(firebaseUser).linkWithCredential(authCredential);
275 |
276 | userTestObserver.assertError(EXCEPTION)
277 | .dispose();
278 |
279 |
280 | }
281 | }
--------------------------------------------------------------------------------
/app/src/main/java/durdinapps/rxfirebase2/RxFirebaseUser.java:
--------------------------------------------------------------------------------
1 | package durdinapps.rxfirebase2;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import com.google.firebase.auth.AuthCredential;
6 | import com.google.firebase.auth.AuthResult;
7 | import com.google.firebase.auth.FirebaseUser;
8 | import com.google.firebase.auth.GetTokenResult;
9 | import com.google.firebase.auth.PhoneAuthCredential;
10 | import com.google.firebase.auth.UserProfileChangeRequest;
11 |
12 | import io.reactivex.Completable;
13 | import io.reactivex.CompletableEmitter;
14 | import io.reactivex.CompletableOnSubscribe;
15 | import io.reactivex.Maybe;
16 | import io.reactivex.MaybeEmitter;
17 | import io.reactivex.MaybeOnSubscribe;
18 |
19 | public class RxFirebaseUser {
20 |
21 | /**
22 | * Fetches a Firebase Auth ID Token for the user; useful when authenticating against your own backend.
23 | *
24 | * @param firebaseUser current firebaseUser instance.
25 | * @param forceRefresh force to refresh the token ID.
26 | * @return a {@link Maybe} which emits an {@link GetTokenResult} if success.
27 | */
28 | @NonNull
29 | public static Maybe getIdToken(@NonNull final FirebaseUser firebaseUser,
30 | final boolean forceRefresh) {
31 | return Maybe.create(new MaybeOnSubscribe() {
32 | @Override
33 | public void subscribe(MaybeEmitter emitter) throws Exception {
34 | RxHandler.assignOnTask(emitter, firebaseUser.getIdToken(forceRefresh));
35 | }
36 | });
37 | }
38 |
39 | /**
40 | * Updates the email address of the user.
41 | *
42 | * @param firebaseUser current firebaseUser instance.
43 | * @param email new email.
44 | * @return a {@link Completable} if the task is complete successfully.
45 | */
46 | @NonNull
47 | public static Completable updateEmail(@NonNull final FirebaseUser firebaseUser,
48 | @NonNull final String email) {
49 | return Completable.create(new CompletableOnSubscribe() {
50 | @Override
51 | public void subscribe(CompletableEmitter emitter) throws Exception {
52 | RxCompletableHandler.assignOnTask(emitter, firebaseUser.updateEmail(email));
53 | }
54 | });
55 | }
56 |
57 | /**
58 | * Updates the password of the user.
59 | *
60 | * @param firebaseUser current firebaseUser instance.
61 | * @param password new password.
62 | * @return a {@link Completable} if the task is complete successfully.
63 | */
64 | @NonNull
65 | public static Completable updatePassword(@NonNull final FirebaseUser firebaseUser,
66 | @NonNull final String password) {
67 | return Completable.create(new CompletableOnSubscribe() {
68 | @Override
69 | public void subscribe(CompletableEmitter emitter) throws Exception {
70 | RxCompletableHandler.assignOnTask(emitter, firebaseUser.updatePassword(password));
71 | }
72 | });
73 | }
74 |
75 | /**
76 | * Updates the user profile information.
77 | *
78 | * @param firebaseUser current firebaseUser instance.
79 | * @param request {@link UserProfileChangeRequest} request for this user.
80 | * @return a {@link Completable} if the task is complete successfully.
81 | */
82 | @NonNull
83 | public static Completable updateProfile(@NonNull final FirebaseUser firebaseUser,
84 | @NonNull final UserProfileChangeRequest request) {
85 | return Completable.create(new CompletableOnSubscribe() {
86 | @Override
87 | public void subscribe(CompletableEmitter emitter) throws Exception {
88 | RxCompletableHandler.assignOnTask(emitter, firebaseUser.updateProfile(request));
89 | }
90 | });
91 | }
92 |
93 | /**
94 | * Deletes the user record from your Firebase project's database.
95 | *
96 | * @param firebaseUser current firebaseUser instance.
97 | * @return a {@link Completable} if the task is complete successfully.
98 | */
99 | @NonNull
100 | public static Completable delete(@NonNull final FirebaseUser firebaseUser) {
101 | return Completable.create(new CompletableOnSubscribe() {
102 | @Override
103 | public void subscribe(CompletableEmitter emitter) throws Exception {
104 | RxCompletableHandler.assignOnTask(emitter, firebaseUser.delete());
105 | }
106 | });
107 | }
108 |
109 | /**
110 | * Reauthenticates the user with the given credential.
111 | *
112 | * @param firebaseUser current firebaseUser instance.
113 | * @param credential {@link AuthCredential} to re-authenticate.
114 | * @return a {@link Completable} if the task is complete successfully.
115 | */
116 | @NonNull
117 | public static Completable reAuthenticate(@NonNull final FirebaseUser firebaseUser,
118 | @NonNull final AuthCredential credential) {
119 | return Completable.create(new CompletableOnSubscribe() {
120 | @Override
121 | public void subscribe(CompletableEmitter emitter) throws Exception {
122 | RxCompletableHandler.assignOnTask(emitter, firebaseUser.reauthenticate(credential));
123 | }
124 | });
125 | }
126 |
127 | /**
128 | * Manually refreshes the data of the current user (for example, attached providers, display name, and so on).
129 | *
130 | * @param firebaseUser current firebaseUser instance.
131 | * @return a {@link Completable} if the task is complete successfully.
132 | */
133 | @NonNull
134 | public static Completable reload(@NonNull final FirebaseUser firebaseUser) {
135 | return Completable.create(new CompletableOnSubscribe() {
136 | @Override
137 | public void subscribe(CompletableEmitter emitter) throws Exception {
138 | RxCompletableHandler.assignOnTask(emitter, firebaseUser.reload());
139 | }
140 | });
141 | }
142 |
143 | /**
144 | * Initiates email verification for the user.
145 | *
146 | * @param firebaseUser current firebaseUser instance.
147 | * @return a {@link Completable} if the task is complete successfully.
148 | */
149 | @NonNull
150 | public static Completable sendEmailVerification(@NonNull final FirebaseUser firebaseUser) {
151 | return Completable.create(new CompletableOnSubscribe() {
152 | @Override
153 | public void subscribe(CompletableEmitter emitter) throws Exception {
154 | RxCompletableHandler.assignOnTask(emitter, firebaseUser.sendEmailVerification());
155 | }
156 | });
157 | }
158 |
159 | /**
160 | * Attaches the given {@link AuthCredential} to the user.
161 | *
162 | * @param firebaseUser current firebaseUser instance.
163 | * @param credential new {@link AuthCredential} to link.
164 | * @return a {@link Maybe} which emits an {@link AuthResult} if success.
165 | */
166 | @NonNull
167 | public static Maybe linkWithCredential(@NonNull final FirebaseUser firebaseUser,
168 | @NonNull final AuthCredential credential) {
169 | return Maybe.create(new MaybeOnSubscribe() {
170 | @Override
171 | public void subscribe(MaybeEmitter emitter) throws Exception {
172 | RxHandler.assignOnTask(emitter, firebaseUser.linkWithCredential(credential));
173 | }
174 | });
175 | }
176 |
177 | /**
178 | * Detaches credentials from a given provider type from this user.
179 | *
180 | * @param firebaseUser current firebaseUser instance.
181 | * @param provider a unique identifier of the type of provider to be unlinked, for example, {@link com.google.firebase.auth.FacebookAuthProvider#PROVIDER_ID}.
182 | * @return a {@link Maybe} which emits an {@link AuthResult} if success.
183 | */
184 | @NonNull
185 | public static Maybe unlink(@NonNull final FirebaseUser firebaseUser,
186 | @NonNull final String provider) {
187 | return Maybe.create(new MaybeOnSubscribe() {
188 | @Override
189 | public void subscribe(MaybeEmitter emitter) throws Exception {
190 | RxHandler.assignOnTask(emitter, firebaseUser.unlink(provider));
191 | }
192 | });
193 | }
194 |
195 | /**
196 | * updates the current phone number for the given user.
197 | *
198 | * @param firebaseUser current firebaseUser instance.
199 | * @param phoneAuthCredential new phone credential.
200 | * @return a {@link Completable} if the task is complete successfully.
201 | */
202 | @NonNull
203 | public static Completable updatePhoneNumber(@NonNull final FirebaseUser firebaseUser,
204 | @NonNull final PhoneAuthCredential phoneAuthCredential) {
205 | return Completable.create(new CompletableOnSubscribe() {
206 | @Override
207 | public void subscribe(CompletableEmitter emitter) throws Exception {
208 | RxCompletableHandler.assignOnTask(emitter, firebaseUser.updatePhoneNumber(phoneAuthCredential));
209 | }
210 | });
211 | }
212 |
213 | /**
214 | * Reauthenticates the user with the given credential, and returns the profile data for that account.
215 | * This is useful for operations that require a recent sign-in, to prevent or resolve a {@link com.google.firebase.auth.FirebaseAuthRecentLoginRequiredException}
216 | *
217 | * @param firebaseUser current firebaseUser instance.
218 | * @param credential Authcredential used for reauthenticate.
219 | * @return a {@link Maybe} which emits an {@link AuthResult} if success.
220 | */
221 | @NonNull
222 | public static Maybe reauthenticateAndRetrieveData(@NonNull final FirebaseUser firebaseUser,
223 | @NonNull final AuthCredential credential) {
224 | return Maybe.create(new MaybeOnSubscribe() {
225 | @Override
226 | public void subscribe(MaybeEmitter emitter) throws Exception {
227 | RxHandler.assignOnTask(emitter, firebaseUser.reauthenticateAndRetrieveData(credential));
228 | }
229 | });
230 | }
231 | }
--------------------------------------------------------------------------------
/app/src/test/java/durdinapps/rxfirebase2/RxFirestoreTest.java:
--------------------------------------------------------------------------------
1 | package durdinapps.rxfirebase2;
2 |
3 | import com.google.android.gms.tasks.Task;
4 | import com.google.firebase.firestore.CollectionReference;
5 | import com.google.firebase.firestore.DocumentReference;
6 | import com.google.firebase.firestore.DocumentSnapshot;
7 | import com.google.firebase.firestore.ListenerRegistration;
8 | import com.google.firebase.firestore.Query;
9 | import com.google.firebase.firestore.QuerySnapshot;
10 |
11 | import org.junit.Before;
12 | import org.junit.Test;
13 | import org.mockito.Mock;
14 | import org.mockito.MockitoAnnotations;
15 | import org.mockito.invocation.InvocationOnMock;
16 | import org.mockito.stubbing.Answer;
17 |
18 | import java.util.ArrayList;
19 | import java.util.Collections;
20 | import java.util.HashMap;
21 | import java.util.Iterator;
22 | import java.util.List;
23 |
24 | import io.reactivex.observers.TestObserver;
25 |
26 | import static durdinapps.rxfirebase2.RxTestUtil.eventSnapshotListener;
27 | import static durdinapps.rxfirebase2.RxTestUtil.setupOfflineTask;
28 | import static durdinapps.rxfirebase2.RxTestUtil.setupTask;
29 | import static durdinapps.rxfirebase2.RxTestUtil.testOnCompleteListener;
30 | import static durdinapps.rxfirebase2.RxTestUtil.testOnSuccessListener;
31 | import static org.mockito.Mockito.verify;
32 | import static org.mockito.Mockito.when;
33 |
34 | public class RxFirestoreTest {
35 |
36 | @Mock
37 | private Task mockVoidTask;
38 |
39 | @Mock
40 | private DocumentReference documentReference;
41 |
42 | @Mock
43 | private DocumentReference emptyDocumentReference;
44 |
45 | @Mock
46 | private CollectionReference collectionReference;
47 |
48 | @Mock
49 | private CollectionReference emptyCollectionReference;
50 |
51 | @Mock
52 | private Query queryReference;
53 |
54 | @Mock
55 | private Query emptyQueryReference;
56 |
57 | @Mock
58 | private DocumentSnapshot documentSnapshot;
59 |
60 | @Mock
61 | private DocumentSnapshot emptyDocumentSnapshot;
62 |
63 | @Mock
64 | private QuerySnapshot querySnapshot;
65 | @Mock
66 | private QuerySnapshot emptyQuerySnapshot;
67 |
68 | @Mock
69 | private Task emptyDocumentSnapshotTask;
70 |
71 | @Mock
72 | private Task documentSnapshotTask;
73 |
74 | @Mock
75 | private Task documentRefTask;
76 |
77 | @Mock
78 | private Task queryResultTask;
79 |
80 | @Mock
81 | private Task emptyQueryResultTask;
82 |
83 | @Mock
84 | private ListenerRegistration registration;
85 |
86 |
87 | private HashMap updateMap = new HashMap<>();
88 | private ChildDocData setData = new ChildDocData();
89 | private ChildDocData childData = new ChildDocData();
90 | private List childDataList = new ArrayList<>();
91 |
92 | @Before
93 | public void setup() {
94 | MockitoAnnotations.initMocks(this);
95 |
96 | setupTask(documentSnapshotTask);
97 | setupTask(emptyDocumentSnapshotTask);
98 | setupTask(queryResultTask);
99 | setupTask(emptyQueryResultTask);
100 | setupTask(mockVoidTask);
101 | setupOfflineTask(documentReference, registration);
102 |
103 | when(documentReference.get()).thenReturn(documentSnapshotTask);
104 | when(emptyDocumentReference.get()).thenReturn(emptyDocumentSnapshotTask);
105 | when(collectionReference.get()).thenReturn(queryResultTask);
106 | when(emptyCollectionReference.get()).thenReturn(emptyQueryResultTask);
107 | when(queryReference.get()).thenReturn(queryResultTask);
108 | when(emptyQueryReference.get()).thenReturn(emptyQueryResultTask);
109 | when(documentReference.delete()).thenReturn(mockVoidTask);
110 | when(documentReference.update(updateMap)).thenReturn(mockVoidTask);
111 | when(collectionReference.add(setData)).thenReturn(documentRefTask);
112 | when(documentSnapshot.toObject(ChildDocData.class)).thenReturn(childData);
113 | when(documentSnapshot.exists()).thenReturn(true); //This snapshots exist
114 | when(documentSnapshot.exists()).thenReturn(true); //This snapshots exist
115 | when(emptyDocumentSnapshot.exists()).thenReturn(false); //This snapshots exist
116 | when(querySnapshot.isEmpty()).thenReturn(false);
117 | when(querySnapshot.toObjects(ChildDocData.class)).thenReturn(childDataList);
118 | when(querySnapshot.iterator()).thenAnswer(new Answer>() {
119 | @Override
120 | public Iterator answer(InvocationOnMock invocation) {
121 | return Collections.singletonList(documentSnapshot).iterator();
122 | }
123 | });
124 | when(emptyQuerySnapshot.isEmpty()).thenReturn(true);
125 | }
126 |
127 | @Test
128 | public void testGetDocument() {
129 | TestObserver testObserver = RxFirestore
130 | .getDocument(documentReference)
131 | .test();
132 |
133 | testOnSuccessListener.getValue().onSuccess(documentSnapshot);
134 |
135 | verify(documentReference).get();
136 |
137 | testObserver
138 | .assertNoErrors()
139 | .assertValueCount(1)
140 | .assertValueSet(Collections.singletonList(documentSnapshot))
141 | .assertComplete();
142 | }
143 |
144 | @Test
145 | public void testGetEmptyDocument() {
146 | TestObserver testObserver = RxFirestore
147 | .getDocument(emptyDocumentReference)
148 | .test();
149 |
150 | testOnSuccessListener.getValue().onSuccess(emptyDocumentSnapshot);
151 |
152 | verify(emptyDocumentReference).get();
153 |
154 | testObserver
155 | .assertNoErrors()
156 | .assertValueCount(0)
157 | .assertComplete();
158 | }
159 |
160 | @Test
161 | public void testMappedGetDocument() {
162 | TestObserver testObserver = RxFirestore
163 | .getDocument(documentReference, ChildDocData.class)
164 | .test();
165 |
166 | testOnSuccessListener.getValue().onSuccess(documentSnapshot);
167 |
168 | verify(documentReference).get();
169 |
170 | testObserver
171 | .assertNoErrors()
172 | .assertValueCount(1)
173 | .assertValueSet(Collections.singletonList(childData))
174 | .assertComplete();
175 | }
176 |
177 | @Test
178 | public void testMappedGetEmptyDocument() {
179 | TestObserver testObserver = RxFirestore
180 | .getDocument(emptyDocumentReference, ChildDocData.class)
181 | .test();
182 |
183 | testOnSuccessListener.getValue().onSuccess(emptyDocumentSnapshot);
184 |
185 | verify(emptyDocumentReference).get();
186 |
187 | testObserver
188 | .assertNoErrors()
189 | .assertValueCount(0)
190 | .assertComplete();
191 | }
192 |
193 | @Test
194 | public void testGetCollection() {
195 | TestObserver testObserver = RxFirestore
196 | .getCollection(collectionReference)
197 | .test();
198 |
199 | testOnSuccessListener.getValue().onSuccess(querySnapshot);
200 |
201 | verify(collectionReference).get();
202 |
203 | testObserver
204 | .assertNoErrors()
205 | .assertValueCount(1)
206 | .assertValueSet(Collections.singletonList(querySnapshot))
207 | .assertComplete();
208 | }
209 |
210 | @Test
211 | public void testGetEmptyCollection() {
212 | TestObserver testObserver = RxFirestore
213 | .getCollection(emptyCollectionReference)
214 | .test();
215 |
216 | testOnSuccessListener.getValue().onSuccess(emptyQuerySnapshot);
217 |
218 | verify(emptyCollectionReference).get();
219 |
220 | testObserver
221 | .assertNoErrors()
222 | .assertValueCount(0)
223 | .assertComplete();
224 | }
225 |
226 | @Test
227 | public void testMappedGetCollection() {
228 | TestObserver> testObserver = RxFirestore
229 | .getCollection(collectionReference, ChildDocData.class)
230 | .test();
231 |
232 | testOnSuccessListener.getValue().onSuccess(querySnapshot);
233 |
234 | verify(collectionReference).get();
235 |
236 | testObserver
237 | .assertNoErrors()
238 | .assertValueCount(1)
239 | .assertComplete();
240 | }
241 |
242 | @Test
243 | public void testMappedGetEmptyCollection() {
244 | TestObserver> testObserver = RxFirestore
245 | .getCollection(emptyCollectionReference, ChildDocData.class)
246 | .test();
247 |
248 | testOnSuccessListener.getValue().onSuccess(emptyQuerySnapshot);
249 |
250 | verify(emptyCollectionReference).get();
251 |
252 | testObserver
253 | .assertNoErrors()
254 | .assertValueCount(0)
255 | .assertComplete();
256 | }
257 |
258 | @Test
259 | public void testGetQuery() {
260 | TestObserver testObserver = RxFirestore
261 | .getCollection(queryReference)
262 | .test();
263 |
264 | testOnSuccessListener.getValue().onSuccess(querySnapshot);
265 |
266 | verify(queryReference).get();
267 |
268 | testObserver
269 | .assertNoErrors()
270 | .assertValueCount(1)
271 | .assertValueSet(Collections.singletonList(querySnapshot))
272 | .assertComplete();
273 | }
274 |
275 | @Test
276 | public void testGetEmptyQuery() {
277 | TestObserver testObserver = RxFirestore
278 | .getCollection(emptyQueryReference)
279 | .test();
280 |
281 | testOnSuccessListener.getValue().onSuccess(emptyQuerySnapshot);
282 |
283 | verify(emptyQueryReference).get();
284 |
285 | testObserver
286 | .assertNoErrors()
287 | .assertValueCount(0)
288 | .assertComplete();
289 | }
290 |
291 | @Test
292 | public void testMappedGetQuery() {
293 | TestObserver> testObserver = RxFirestore
294 | .getCollection(queryReference, ChildDocData.class)
295 | .test();
296 |
297 | testOnSuccessListener.getValue().onSuccess(querySnapshot);
298 |
299 | verify(queryReference).get();
300 |
301 | testObserver
302 | .assertNoErrors()
303 | .assertValueCount(1)
304 | .assertComplete();
305 | }
306 |
307 | @Test
308 | public void testMappedGetEmptyQuery() {
309 | TestObserver> testObserver = RxFirestore
310 | .getCollection(emptyQueryReference, ChildDocData.class)
311 | .test();
312 |
313 | testOnSuccessListener.getValue().onSuccess(emptyQuerySnapshot);
314 |
315 | verify(emptyQueryReference).get();
316 |
317 | testObserver
318 | .assertNoErrors()
319 | .assertValueCount(0)
320 | .assertComplete();
321 | }
322 |
323 | @Test
324 | public void testSetDocumentOffline() {
325 | TestObserver testObserver = RxFirestore
326 | .setDocumentOffline(documentReference, setData)
327 | .test();
328 |
329 | eventSnapshotListener.getValue().onEvent(documentSnapshot, null);
330 |
331 | verify(documentReference).set(setData);
332 |
333 | testObserver
334 | .assertNoErrors()
335 | .assertComplete();
336 | }
337 |
338 | @Test
339 | public void testUpdateDocument() {
340 |
341 | TestObserver storageTestObserver =
342 | RxFirestore.updateDocument(documentReference, updateMap)
343 | .test();
344 |
345 | testOnCompleteListener.getValue().onComplete(mockVoidTask);
346 |
347 | verify(documentReference).update(updateMap);
348 |
349 | storageTestObserver.assertNoErrors()
350 | .assertComplete()
351 | .dispose();
352 | }
353 |
354 |
355 | @Test
356 | public void testUpdateDocumentOffline() {
357 | TestObserver testObserver = RxFirestore
358 | .updateDocumentOffline(documentReference, updateMap)
359 | .test();
360 |
361 | eventSnapshotListener.getValue().onEvent(documentSnapshot, null);
362 |
363 | verify(documentReference).update(updateMap);
364 |
365 | testObserver
366 | .assertNoErrors()
367 | .assertComplete();
368 | }
369 |
370 |
371 | @Test
372 | public void testDeleteDocument() {
373 |
374 | TestObserver storageTestObserver =
375 | RxFirestore.deleteDocument(documentReference)
376 | .test();
377 |
378 | testOnCompleteListener.getValue().onComplete(mockVoidTask);
379 |
380 | verify(documentReference).delete();
381 |
382 | storageTestObserver.assertNoErrors()
383 | .assertComplete()
384 | .dispose();
385 | }
386 |
387 | @Test
388 | public void testDeleteDocumentOffline() {
389 | TestObserver testObserver = RxFirestore
390 | .deleteDocumentOffline(documentReference)
391 | .test();
392 |
393 | eventSnapshotListener.getValue().onEvent(documentSnapshot, null);
394 | verify(documentReference).delete();
395 |
396 | testObserver
397 | .assertNoErrors()
398 | .assertComplete();
399 | }
400 |
401 |
402 | class ChildDocData {
403 | int id;
404 | String str;
405 | }
406 | }
407 |
--------------------------------------------------------------------------------
/app/src/test/java/durdinapps/rxfirebase2/RxFirebaseAuthTest.java:
--------------------------------------------------------------------------------
1 | package durdinapps.rxfirebase2;
2 |
3 |
4 | import com.google.android.gms.tasks.Task;
5 | import com.google.firebase.auth.ActionCodeResult;
6 | import com.google.firebase.auth.AuthCredential;
7 | import com.google.firebase.auth.AuthResult;
8 | import com.google.firebase.auth.FirebaseAuth;
9 | import com.google.firebase.auth.FirebaseUser;
10 | import com.google.firebase.auth.SignInMethodQueryResult;
11 | import com.google.firebase.database.DataSnapshot;
12 |
13 | import org.junit.Before;
14 | import org.junit.Test;
15 | import org.mockito.ArgumentCaptor;
16 | import org.mockito.Mock;
17 | import org.mockito.MockitoAnnotations;
18 |
19 | import java.util.Collections;
20 |
21 | import io.reactivex.observers.TestObserver;
22 |
23 | import static durdinapps.rxfirebase2.RxTestUtil.ANY_CODE;
24 | import static durdinapps.rxfirebase2.RxTestUtil.ANY_EMAIL;
25 | import static durdinapps.rxfirebase2.RxTestUtil.ANY_PASSWORD;
26 | import static durdinapps.rxfirebase2.RxTestUtil.ANY_TOKEN;
27 | import static durdinapps.rxfirebase2.RxTestUtil.EXCEPTION;
28 | import static durdinapps.rxfirebase2.RxTestUtil.RESULT_CODE;
29 | import static durdinapps.rxfirebase2.RxTestUtil.setupTask;
30 | import static durdinapps.rxfirebase2.RxTestUtil.testOnCompleteListener;
31 | import static durdinapps.rxfirebase2.RxTestUtil.testOnFailureListener;
32 | import static durdinapps.rxfirebase2.RxTestUtil.testOnSuccessListener;
33 | import static org.mockito.ArgumentMatchers.eq;
34 | import static org.mockito.Mockito.verify;
35 | import static org.mockito.Mockito.when;
36 |
37 | public class RxFirebaseAuthTest {
38 |
39 | @Mock
40 | private FirebaseAuth firebaseAuth;
41 |
42 | @Mock
43 | private Task authResultTask;
44 |
45 | @Mock
46 | private Task providerQueryResultTask;
47 |
48 | @Mock
49 | private Task actionCodeResultTask;
50 |
51 | @Mock
52 | private Task checkCodeResultTask;
53 |
54 | @Mock
55 | private Task voidTask;
56 |
57 | @Mock
58 | private AuthResult authResult;
59 |
60 | @Mock
61 | private SignInMethodQueryResult providerQueryResult;
62 |
63 | @Mock
64 | private ActionCodeResult actionCodeResult;
65 |
66 | @Mock
67 | private DataSnapshot dataSnapshot;
68 |
69 | @Mock
70 | private AuthCredential authCredential;
71 |
72 | @Mock
73 | private FirebaseUser firebaseUser;
74 |
75 |
76 | @Before
77 | public void setup() {
78 | MockitoAnnotations.initMocks(this);
79 |
80 | setupTask(authResultTask);
81 | setupTask(providerQueryResultTask);
82 | setupTask(actionCodeResultTask);
83 | setupTask(checkCodeResultTask);
84 | setupTask(voidTask);
85 |
86 | when(firebaseAuth.signInAnonymously()).thenReturn(authResultTask);
87 | when(firebaseAuth.signInWithEmailAndPassword(ANY_EMAIL, ANY_PASSWORD)).thenReturn(authResultTask);
88 | when(firebaseAuth.signInWithCredential(authCredential)).thenReturn(authResultTask);
89 | when(firebaseAuth.signInWithCustomToken(ANY_TOKEN)).thenReturn(authResultTask);
90 | when(firebaseAuth.createUserWithEmailAndPassword(ANY_EMAIL, ANY_PASSWORD)).thenReturn(authResultTask);
91 | when(firebaseAuth.fetchSignInMethodsForEmail(ANY_EMAIL)).thenReturn(providerQueryResultTask);
92 | when(firebaseAuth.checkActionCode(ANY_CODE)).thenReturn(actionCodeResultTask);
93 | when(firebaseAuth.verifyPasswordResetCode(ANY_CODE)).thenReturn(checkCodeResultTask);
94 | when(firebaseAuth.sendPasswordResetEmail(ANY_EMAIL)).thenReturn(voidTask);
95 | when(firebaseAuth.confirmPasswordReset(ANY_CODE, ANY_PASSWORD)).thenReturn(voidTask);
96 | when(firebaseAuth.applyActionCode(ANY_CODE)).thenReturn(voidTask);
97 |
98 | when(firebaseAuth.getCurrentUser()).thenReturn(firebaseUser);
99 |
100 | }
101 |
102 | @Test
103 | public void signInAnonymously() {
104 |
105 | TestObserver authTestObserver = RxFirebaseAuth
106 | .signInAnonymously(firebaseAuth)
107 | .test();
108 |
109 | testOnSuccessListener.getValue().onSuccess(authResult);
110 | testOnCompleteListener.getValue().onComplete(authResultTask);
111 |
112 | verify(firebaseAuth).signInAnonymously();
113 |
114 | authTestObserver
115 | .assertNoErrors()
116 | .assertValueCount(1)
117 | .assertValueSet(Collections.singletonList(authResult))
118 | .assertComplete();
119 | }
120 |
121 | @Test
122 | public void signInAnonymouslyError() {
123 |
124 | TestObserver authTestObserver = RxFirebaseAuth
125 | .signInAnonymously(firebaseAuth)
126 | .test();
127 |
128 | testOnFailureListener.getValue().onFailure(EXCEPTION);
129 |
130 | verify(firebaseAuth).signInAnonymously();
131 |
132 | authTestObserver.assertError(EXCEPTION)
133 | .assertNotComplete();
134 | }
135 |
136 | @Test
137 | public void createUserWithEmailAndPassword() {
138 | TestObserver authTestObserver = RxFirebaseAuth
139 | .createUserWithEmailAndPassword(firebaseAuth, ANY_EMAIL, ANY_PASSWORD)
140 | .test();
141 |
142 | testOnSuccessListener.getValue().onSuccess(authResult);
143 | testOnCompleteListener.getValue().onComplete(authResultTask);
144 |
145 | verify(firebaseAuth).createUserWithEmailAndPassword(ANY_EMAIL, ANY_PASSWORD);
146 |
147 | authTestObserver.assertNoErrors()
148 | .assertValueCount(1)
149 | .assertValueSet(Collections.singletonList(authResult))
150 | .assertComplete()
151 | .dispose();
152 | }
153 |
154 | @Test
155 | public void createUserWithEmailAndPasswordError() {
156 |
157 | TestObserver authTestObserver = RxFirebaseAuth
158 | .createUserWithEmailAndPassword(firebaseAuth, ANY_EMAIL, ANY_PASSWORD)
159 | .test();
160 |
161 | testOnFailureListener.getValue().onFailure(EXCEPTION);
162 |
163 | verify(firebaseAuth).createUserWithEmailAndPassword(ANY_EMAIL, ANY_PASSWORD);
164 |
165 | authTestObserver.assertError(EXCEPTION)
166 | .assertNotComplete()
167 | .dispose();
168 | }
169 |
170 | @Test
171 | public void signInWithEmailAndPassword() {
172 |
173 | TestObserver authTestObserver = RxFirebaseAuth
174 | .signInWithEmailAndPassword(firebaseAuth, ANY_EMAIL, ANY_PASSWORD)
175 | .test();
176 |
177 | testOnSuccessListener.getValue().onSuccess(authResult);
178 | testOnCompleteListener.getValue().onComplete(authResultTask);
179 |
180 | verify(firebaseAuth).signInWithEmailAndPassword(eq(ANY_EMAIL), eq(ANY_PASSWORD));
181 |
182 | authTestObserver.assertNoErrors()
183 | .assertValueCount(1)
184 | .assertValueSet(Collections.singletonList(authResult))
185 | .assertComplete()
186 | .dispose();
187 | }
188 |
189 | @Test
190 | public void signInWithEmailAndPasswordError() {
191 |
192 | TestObserver authTestObserver = RxFirebaseAuth
193 | .signInWithEmailAndPassword(firebaseAuth, ANY_EMAIL, ANY_PASSWORD)
194 | .test();
195 |
196 | testOnFailureListener.getValue().onFailure(EXCEPTION);
197 |
198 | verify(firebaseAuth).signInWithEmailAndPassword(eq(ANY_EMAIL), eq(ANY_PASSWORD));
199 |
200 | authTestObserver.assertError(EXCEPTION)
201 | .assertNotComplete()
202 | .dispose();
203 | }
204 |
205 | @Test
206 | public void signInWithCredential() {
207 |
208 | TestObserver authTestObserver = RxFirebaseAuth
209 | .signInWithCredential(firebaseAuth, authCredential)
210 | .test();
211 |
212 | testOnSuccessListener.getValue().onSuccess(authResult);
213 | testOnCompleteListener.getValue().onComplete(authResultTask);
214 |
215 | verify(firebaseAuth).signInWithCredential(authCredential);
216 |
217 | authTestObserver.assertNoErrors()
218 | .assertValueCount(1)
219 | .assertValueSet(Collections.singletonList(authResult))
220 | .assertComplete()
221 | .dispose();
222 | }
223 |
224 | @Test
225 | public void signInWithCredentialError() {
226 |
227 | TestObserver authTestObserver = RxFirebaseAuth
228 | .signInWithCredential(firebaseAuth, authCredential)
229 | .test();
230 |
231 | testOnFailureListener.getValue().onFailure(EXCEPTION);
232 |
233 | verify(firebaseAuth).signInWithCredential(authCredential);
234 |
235 | authTestObserver.assertError(EXCEPTION)
236 | .assertNotComplete()
237 | .dispose();
238 | }
239 |
240 | @Test
241 | public void signInWithCustomToken() {
242 |
243 | TestObserver authTestObserver = RxFirebaseAuth
244 | .signInWithCustomToken(firebaseAuth, ANY_TOKEN)
245 | .test();
246 |
247 | testOnSuccessListener.getValue().onSuccess(authResult);
248 | testOnCompleteListener.getValue().onComplete(authResultTask);
249 |
250 | verify(firebaseAuth).signInWithCustomToken(eq(ANY_TOKEN));
251 |
252 | authTestObserver.assertNoErrors()
253 | .assertValueCount(1)
254 | .assertValueSet(Collections.singletonList(authResult))
255 | .assertComplete()
256 | .dispose();
257 | }
258 |
259 | @Test
260 | public void signInWithCustomTokenError() {
261 |
262 | TestObserver authTestObserver = RxFirebaseAuth
263 | .signInWithCustomToken(firebaseAuth, ANY_TOKEN)
264 | .test();
265 |
266 | testOnFailureListener.getValue().onFailure(EXCEPTION);
267 |
268 | verify(firebaseAuth).signInWithCustomToken(eq(ANY_TOKEN));
269 |
270 | authTestObserver.assertError(EXCEPTION)
271 | .assertNotComplete()
272 | .dispose();
273 | }
274 |
275 | @Test
276 | public void fetchProvidersForEmail() {
277 |
278 | TestObserver authTestObserver = RxFirebaseAuth
279 | .fetchSignInMethodsForEmail(firebaseAuth, ANY_EMAIL)
280 | .test();
281 |
282 | testOnSuccessListener.getValue().onSuccess(providerQueryResult);
283 | testOnCompleteListener.getValue().onComplete(providerQueryResultTask);
284 |
285 | verify(firebaseAuth).fetchSignInMethodsForEmail(eq(ANY_EMAIL));
286 |
287 | authTestObserver.assertNoErrors()
288 | .assertValueCount(1)
289 | .assertValueSet(Collections.singletonList(providerQueryResult))
290 | .assertComplete()
291 | .dispose();
292 | }
293 |
294 | @Test
295 | public void checkActionCode() {
296 |
297 | TestObserver authTestObserver = RxFirebaseAuth
298 | .checkActionCode(firebaseAuth, ANY_CODE)
299 | .test();
300 |
301 | testOnSuccessListener.getValue().onSuccess(actionCodeResult);
302 | testOnCompleteListener.getValue().onComplete(actionCodeResultTask);
303 |
304 | verify(firebaseAuth).checkActionCode(eq(ANY_CODE));
305 |
306 | authTestObserver.assertNoErrors()
307 | .assertValueCount(1)
308 | .assertValueSet(Collections.singletonList(actionCodeResult))
309 | .assertComplete()
310 | .dispose();
311 | }
312 |
313 | @Test
314 | public void fetchProvidersForEmailError() {
315 |
316 | TestObserver authTestObserver = RxFirebaseAuth
317 | .fetchSignInMethodsForEmail(firebaseAuth, ANY_EMAIL)
318 | .test();
319 |
320 | testOnFailureListener.getValue().onFailure(EXCEPTION);
321 |
322 | verify(firebaseAuth).fetchSignInMethodsForEmail(ANY_EMAIL);
323 |
324 | authTestObserver.assertError(EXCEPTION)
325 | .assertNotComplete()
326 | .dispose();
327 | }
328 |
329 | @Test
330 | public void verifyPasswordResetCode() {
331 |
332 | TestObserver authTestObserver = RxFirebaseAuth
333 | .verifyPasswordResetCode(firebaseAuth, ANY_CODE)
334 | .test();
335 |
336 | testOnSuccessListener.getValue().onSuccess(RESULT_CODE);
337 | testOnCompleteListener.getValue().onComplete(checkCodeResultTask);
338 |
339 | verify(firebaseAuth).verifyPasswordResetCode(ANY_CODE);
340 |
341 | authTestObserver.assertNoErrors()
342 | .assertValueCount(1)
343 | .assertValueSet(Collections.singletonList(RESULT_CODE))
344 | .assertComplete()
345 | .dispose();
346 | }
347 |
348 | @Test
349 | public void sendPasswordResetEmail() {
350 | TestObserver authTestObserver = RxFirebaseAuth
351 | .sendPasswordResetEmail(firebaseAuth, ANY_EMAIL)
352 | .test();
353 |
354 | testOnCompleteListener.getValue().onComplete(voidTask);
355 |
356 | verify(firebaseAuth).sendPasswordResetEmail(eq(ANY_EMAIL));
357 |
358 | authTestObserver.assertNoErrors()
359 | .assertValueSet(Collections.singletonList(voidTask))
360 | .assertComplete()
361 | .dispose();
362 | }
363 |
364 | @Test
365 | public void confirmPasswordReset() {
366 | TestObserver authTestObserver = RxFirebaseAuth
367 | .confirmPasswordReset(firebaseAuth, ANY_CODE, ANY_PASSWORD)
368 | .test();
369 |
370 | testOnCompleteListener.getValue().onComplete(voidTask);
371 |
372 | verify(firebaseAuth).confirmPasswordReset(eq(ANY_CODE), eq(ANY_PASSWORD));
373 |
374 | authTestObserver.assertNoErrors()
375 | .assertValueSet(Collections.singletonList(voidTask))
376 | .assertComplete()
377 | .dispose();
378 | }
379 |
380 | @Test
381 | public void applyActionCode() {
382 | TestObserver authTestObserver = RxFirebaseAuth
383 | .applyActionCode(firebaseAuth, ANY_CODE)
384 | .test();
385 |
386 | testOnCompleteListener.getValue().onComplete(voidTask);
387 |
388 | verify(firebaseAuth).applyActionCode(eq(ANY_CODE));
389 |
390 | authTestObserver.assertNoErrors()
391 | .assertValueSet(Collections.singletonList(voidTask))
392 | .assertComplete()
393 | .dispose();
394 | }
395 |
396 | @Test
397 | public void sendPasswordResetEmailError() {
398 |
399 | TestObserver authTestObserver = RxFirebaseAuth
400 | .sendPasswordResetEmail(firebaseAuth, ANY_EMAIL)
401 | .test();
402 |
403 | testOnFailureListener.getValue().onFailure(EXCEPTION);
404 |
405 | verify(firebaseAuth).sendPasswordResetEmail(eq(ANY_EMAIL));
406 |
407 | authTestObserver.assertError(EXCEPTION)
408 | .assertNotComplete()
409 | .dispose();
410 | }
411 |
412 | @Test
413 | public void testObserveAuthState() {
414 |
415 | TestObserver authTestObserver = RxFirebaseAuth
416 | .observeAuthState(firebaseAuth)
417 | .test();
418 |
419 | ArgumentCaptor argument = ArgumentCaptor.forClass(FirebaseAuth.AuthStateListener.class);
420 | verify(firebaseAuth).addAuthStateListener(argument.capture());
421 | argument.getValue().onAuthStateChanged(firebaseAuth);
422 |
423 | authTestObserver.assertNoErrors()
424 | .assertValueCount(1)
425 | .assertValueSet(Collections.singletonList(firebaseAuth))
426 | .assertNotComplete()
427 | .dispose();
428 | }
429 | }
430 |
--------------------------------------------------------------------------------
/app/src/test/java/durdinapps/rxfirebase2/RxFirebaseStorageTest.java:
--------------------------------------------------------------------------------
1 | package durdinapps.rxfirebase2;
2 |
3 |
4 | import android.net.Uri;
5 |
6 | import com.google.android.gms.tasks.Task;
7 | import com.google.firebase.storage.FileDownloadTask;
8 | import com.google.firebase.storage.StorageMetadata;
9 | import com.google.firebase.storage.StorageReference;
10 | import com.google.firebase.storage.StreamDownloadTask;
11 | import com.google.firebase.storage.UploadTask;
12 |
13 | import org.junit.Before;
14 | import org.junit.Test;
15 | import org.mockito.Mock;
16 | import org.mockito.MockitoAnnotations;
17 |
18 | import java.io.File;
19 | import java.io.InputStream;
20 | import java.util.Collections;
21 |
22 | import io.reactivex.observers.TestObserver;
23 |
24 | import static durdinapps.rxfirebase2.RxTestUtil.NULL_FIREBASE_EXCEPTION;
25 | import static durdinapps.rxfirebase2.RxTestUtil.setupTask;
26 | import static durdinapps.rxfirebase2.RxTestUtil.testOnCompleteListener;
27 | import static durdinapps.rxfirebase2.RxTestUtil.testOnFailureListener;
28 | import static durdinapps.rxfirebase2.RxTestUtil.testOnSuccessListener;
29 | import static org.mockito.Mockito.verify;
30 | import static org.mockito.Mockito.when;
31 |
32 | public class RxFirebaseStorageTest {
33 |
34 | @Mock
35 | private StorageReference mockStorageRef;
36 |
37 | @Mock
38 | private Task mockVoidTask;
39 |
40 | @Mock
41 | private Task mockBytesTask;
42 |
43 | @Mock
44 | private Task mockUriTask;
45 |
46 | @Mock
47 | private FileDownloadTask mockFileDownloadTask;
48 |
49 | @Mock
50 | private StreamDownloadTask mockStreamDownloadTask;
51 |
52 | @Mock
53 | private Task mockMetadataTask;
54 |
55 | @Mock
56 | private UploadTask mockUploadTask;
57 |
58 | @Mock
59 | private Uri uri;
60 |
61 | @Mock
62 | private File file;
63 |
64 | @Mock
65 | private StorageMetadata metadata;
66 |
67 | @Mock
68 | private FileDownloadTask.TaskSnapshot fileSnapshot;
69 |
70 | @Mock
71 | private StreamDownloadTask.TaskSnapshot streamSnapshot;
72 |
73 | @Mock
74 | private UploadTask.TaskSnapshot uploadSnapshot;
75 |
76 | private byte[] nullBytes;
77 |
78 | private byte[] notNullbytes = new byte[0];
79 |
80 | @Mock
81 | private StreamDownloadTask.StreamProcessor processor;
82 |
83 | @Mock
84 | private InputStream stream;
85 |
86 | private Void voidData = null;
87 |
88 |
89 | @Before
90 | public void setup() {
91 | MockitoAnnotations.initMocks(this);
92 |
93 | setupTask(mockBytesTask);
94 | setupTask(mockVoidTask);
95 | setupTask(mockUriTask);
96 | setupTask(mockFileDownloadTask);
97 | setupTask(mockStreamDownloadTask);
98 | setupTask(mockMetadataTask);
99 | setupTask(mockUploadTask);
100 |
101 | when(mockStorageRef.getBytes(20)).thenReturn(mockBytesTask);
102 | when(mockStorageRef.getDownloadUrl()).thenReturn(mockUriTask);
103 | when(mockStorageRef.getFile(file)).thenReturn(mockFileDownloadTask);
104 | when(mockStorageRef.getFile(uri)).thenReturn(mockFileDownloadTask);
105 | when(mockStorageRef.getStream()).thenReturn(mockStreamDownloadTask);
106 | when(mockStorageRef.getStream(processor)).thenReturn(mockStreamDownloadTask);
107 | when(mockStorageRef.getMetadata()).thenReturn(mockMetadataTask);
108 | when(mockStorageRef.putBytes(notNullbytes)).thenReturn(mockUploadTask);
109 | when(mockStorageRef.putBytes(nullBytes)).thenReturn(mockUploadTask);
110 | when(mockStorageRef.putBytes(notNullbytes, metadata)).thenReturn(mockUploadTask);
111 | when(mockStorageRef.putBytes(nullBytes, metadata)).thenReturn(mockUploadTask);
112 | when(mockStorageRef.putFile(uri)).thenReturn(mockUploadTask);
113 | when(mockStorageRef.putFile(uri, metadata)).thenReturn(mockUploadTask);
114 | when(mockStorageRef.putFile(uri, metadata, uri)).thenReturn(mockUploadTask);
115 | when(mockStorageRef.putStream(stream)).thenReturn(mockUploadTask);
116 | when(mockStorageRef.putStream(stream, metadata)).thenReturn(mockUploadTask);
117 | when(mockStorageRef.updateMetadata(metadata)).thenReturn(mockMetadataTask);
118 | when(mockStorageRef.delete()).thenReturn(mockVoidTask);
119 | }
120 |
121 | @Test
122 | public void getBytes() {
123 | TestObserver storageTestObserver =
124 | RxFirebaseStorage.getBytes(mockStorageRef, 20)
125 | .test();
126 |
127 | testOnSuccessListener.getValue().onSuccess(notNullbytes);
128 | testOnCompleteListener.getValue().onComplete(mockBytesTask);
129 |
130 | verify(mockStorageRef).getBytes(20);
131 |
132 | storageTestObserver.assertNoErrors()
133 | .assertValueCount(1)
134 | .assertValueSet(Collections.singletonList(notNullbytes))
135 | .assertComplete()
136 | .dispose();
137 | }
138 |
139 | @Test
140 | public void getBytesNoData() {
141 | TestObserver storageTestObserver =
142 | RxFirebaseStorage.getBytes(mockStorageRef, 20)
143 | .test();
144 |
145 | testOnFailureListener.getValue().onFailure(NULL_FIREBASE_EXCEPTION);
146 |
147 | verify(mockStorageRef).getBytes(20);
148 |
149 | storageTestObserver.assertError(NULL_FIREBASE_EXCEPTION)
150 | .assertValueSet(Collections.singletonList(nullBytes))
151 | .assertNotComplete()
152 | .dispose();
153 | }
154 |
155 | @Test
156 | public void getDownloadUrl() {
157 | TestObserver storageTestObserver =
158 | RxFirebaseStorage.getDownloadUrl(mockStorageRef)
159 | .test();
160 |
161 | testOnSuccessListener.getValue().onSuccess(uri);
162 | testOnCompleteListener.getValue().onComplete(mockUriTask);
163 |
164 | verify(mockStorageRef).getDownloadUrl();
165 |
166 | storageTestObserver.assertNoErrors()
167 | .assertValueCount(1)
168 | .assertValueSet(Collections.singletonList(uri))
169 | .assertComplete()
170 | .dispose();
171 | }
172 |
173 | @Test
174 | public void getFile() {
175 |
176 | TestObserver storageTestObserver =
177 | RxFirebaseStorage.getFile(mockStorageRef, file)
178 | .test();
179 |
180 | testOnSuccessListener.getValue().onSuccess(fileSnapshot);
181 |
182 | verify(mockStorageRef).getFile(file);
183 |
184 | storageTestObserver.assertNoErrors()
185 | .assertValueCount(1)
186 | .assertValueSet(Collections.singletonList(fileSnapshot))
187 | .assertComplete()
188 | .dispose();
189 | }
190 |
191 | @Test
192 | public void getFileUri() {
193 |
194 | TestObserver storageTestObserver =
195 | RxFirebaseStorage.getFile(mockStorageRef, uri)
196 | .test();
197 |
198 | testOnSuccessListener.getValue().onSuccess(fileSnapshot);
199 |
200 | verify(mockStorageRef).getFile(uri);
201 |
202 | storageTestObserver.assertNoErrors()
203 | .assertValueCount(1)
204 | .assertValueSet(Collections.singletonList(fileSnapshot))
205 | .assertComplete()
206 | .dispose();
207 | }
208 |
209 |
210 | @Test
211 | public void getMetadata() {
212 |
213 | TestObserver storageTestObserver =
214 | RxFirebaseStorage.getMetadata(mockStorageRef)
215 | .test();
216 |
217 | testOnSuccessListener.getValue().onSuccess(metadata);
218 | testOnCompleteListener.getValue().onComplete(mockMetadataTask);
219 |
220 | verify(mockStorageRef).getMetadata();
221 |
222 | storageTestObserver.assertNoErrors()
223 | .assertValueCount(1)
224 | .assertValueSet(Collections.singletonList(metadata))
225 | .assertComplete()
226 | .dispose();
227 | }
228 |
229 |
230 | @Test
231 | public void getStream() {
232 |
233 | TestObserver storageTestObserver =
234 | RxFirebaseStorage.getStream(mockStorageRef)
235 | .test();
236 |
237 | testOnSuccessListener.getValue().onSuccess(streamSnapshot);
238 |
239 | verify(mockStorageRef).getStream();
240 |
241 | storageTestObserver.assertNoErrors();
242 | storageTestObserver.assertValueCount(1);
243 | storageTestObserver.assertValueSet(Collections.singletonList(streamSnapshot));
244 | storageTestObserver.assertComplete();
245 | storageTestObserver.dispose();
246 | }
247 |
248 | @Test
249 | public void getStreamProcessor() {
250 |
251 | TestObserver storageTestObserver =
252 | RxFirebaseStorage.getStream(mockStorageRef, processor)
253 | .test();
254 |
255 | testOnSuccessListener.getValue().onSuccess(streamSnapshot);
256 |
257 | verify(mockStorageRef).getStream(processor);
258 |
259 | storageTestObserver.assertNoErrors()
260 | .assertValueCount(1)
261 | .assertValueSet(Collections.singletonList(streamSnapshot))
262 | .assertComplete()
263 | .dispose();
264 | }
265 |
266 | @Test
267 | public void putBytes() {
268 |
269 | TestObserver storageTestObserver =
270 | RxFirebaseStorage.putBytes(mockStorageRef, notNullbytes)
271 | .test();
272 |
273 | testOnSuccessListener.getValue().onSuccess(uploadSnapshot);
274 |
275 | verify(mockStorageRef).putBytes(notNullbytes);
276 |
277 | storageTestObserver.assertNoErrors()
278 | .assertValueCount(1)
279 | .assertValueSet(Collections.singletonList(uploadSnapshot))
280 | .assertComplete()
281 | .dispose();
282 | }
283 |
284 | @Test
285 | public void putBytesNoData() {
286 |
287 | TestObserver storageTestObserver =
288 | RxFirebaseStorage.putBytes(mockStorageRef, nullBytes)
289 | .test();
290 |
291 | testOnFailureListener.getValue().onFailure(NULL_FIREBASE_EXCEPTION);
292 |
293 | verify(mockStorageRef).putBytes(nullBytes);
294 |
295 | storageTestObserver.assertError(NULL_FIREBASE_EXCEPTION)
296 | .assertValueSet(Collections.singletonList(uploadSnapshot))
297 | .assertNotComplete()
298 | .dispose();
299 | }
300 |
301 | @Test
302 | public void putBytesMetadata() {
303 |
304 | TestObserver storageTestObserver =
305 | RxFirebaseStorage.putBytes(mockStorageRef, notNullbytes, metadata)
306 | .test();
307 |
308 |
309 | testOnSuccessListener.getValue().onSuccess(uploadSnapshot);
310 | testOnCompleteListener.getValue().onComplete(mockVoidTask);
311 |
312 | verify(mockStorageRef).putBytes(notNullbytes, metadata);
313 |
314 | storageTestObserver.assertNoErrors()
315 | .assertValueCount(1)
316 | .assertValueSet(Collections.singletonList(uploadSnapshot))
317 | .assertComplete()
318 | .dispose();
319 | }
320 |
321 | @Test
322 | public void putFile() {
323 |
324 | TestObserver storageTestObserver =
325 | RxFirebaseStorage.putFile(mockStorageRef, uri)
326 | .test();
327 |
328 | testOnSuccessListener.getValue().onSuccess(uploadSnapshot);
329 |
330 | verify(mockStorageRef).putFile(uri);
331 |
332 | storageTestObserver.assertNoErrors()
333 | .assertValueCount(1)
334 | .assertValueSet(Collections.singletonList(uploadSnapshot))
335 | .assertComplete()
336 | .dispose();
337 | }
338 |
339 | @Test
340 | public void putFileMetadata() {
341 |
342 | TestObserver storageTestObserver =
343 | RxFirebaseStorage.putFile(mockStorageRef, uri, metadata)
344 | .test();
345 |
346 | testOnSuccessListener.getValue().onSuccess(uploadSnapshot);
347 |
348 | verify(mockStorageRef).putFile(uri, metadata);
349 |
350 | storageTestObserver.assertNoErrors()
351 | .assertValueCount(1)
352 | .assertValueSet(Collections.singletonList(uploadSnapshot))
353 | .assertComplete()
354 | .dispose();
355 | }
356 |
357 | @Test
358 | public void putFileMetadataAndUri() {
359 |
360 | TestObserver storageTestObserver =
361 | RxFirebaseStorage.putFile(mockStorageRef, uri, metadata, uri)
362 | .test();
363 |
364 | testOnSuccessListener.getValue().onSuccess(uploadSnapshot);
365 |
366 | verify(mockStorageRef).putFile(uri, metadata, uri);
367 |
368 | storageTestObserver.assertNoErrors()
369 | .assertValueCount(1)
370 | .assertValueSet(Collections.singletonList(uploadSnapshot))
371 | .assertComplete()
372 | .dispose();
373 | }
374 |
375 | @Test
376 | public void putStream() {
377 |
378 | TestObserver storageTestObserver =
379 | RxFirebaseStorage.putStream(mockStorageRef, stream)
380 | .test();
381 |
382 | testOnSuccessListener.getValue().onSuccess(uploadSnapshot);
383 |
384 | verify(mockStorageRef).putStream(stream);
385 |
386 | storageTestObserver.assertNoErrors()
387 | .assertValueCount(1)
388 | .assertValueSet(Collections.singletonList(uploadSnapshot))
389 | .assertComplete()
390 | .dispose();
391 | }
392 |
393 | @Test
394 | public void putStreamMetadata() {
395 |
396 | TestObserver storageTestObserver =
397 | RxFirebaseStorage.putStream(mockStorageRef, stream, metadata)
398 | .test();
399 |
400 | testOnSuccessListener.getValue().onSuccess(uploadSnapshot);
401 |
402 | verify(mockStorageRef).putStream(stream, metadata);
403 |
404 | storageTestObserver.assertNoErrors()
405 | .assertValueCount(1)
406 | .assertValueSet(Collections.singletonList(uploadSnapshot))
407 | .assertComplete()
408 | .dispose();
409 | }
410 |
411 | @Test
412 | public void updateMetadata() {
413 |
414 | TestObserver storageTestObserver =
415 | RxFirebaseStorage.updateMetadata(mockStorageRef, metadata)
416 | .test();
417 |
418 | testOnSuccessListener.getValue().onSuccess(metadata);
419 |
420 | verify(mockStorageRef).updateMetadata(metadata);
421 |
422 | storageTestObserver.assertNoErrors()
423 | .assertValueCount(1)
424 | .assertValueSet(Collections.singletonList(metadata))
425 | .assertComplete()
426 | .dispose();
427 | }
428 |
429 | @Test
430 | public void delete() {
431 |
432 | TestObserver storageTestObserver =
433 | RxFirebaseStorage.delete(mockStorageRef)
434 | .test();
435 |
436 | testOnSuccessListener.getValue().onSuccess(voidData);
437 | testOnCompleteListener.getValue().onComplete(mockVoidTask);
438 |
439 | verify(mockStorageRef).delete();
440 |
441 | storageTestObserver.assertNoErrors()
442 | .assertComplete()
443 | .dispose();
444 | }
445 | }
446 |
--------------------------------------------------------------------------------
/app/src/test/java/durdinapps/rxfirebase2/RxFirebaseDatabaseTest.java:
--------------------------------------------------------------------------------
1 | package durdinapps.rxfirebase2;
2 |
3 |
4 | import android.app.DownloadManager;
5 |
6 | import com.google.android.gms.tasks.Task;
7 | import com.google.firebase.database.ChildEventListener;
8 | import com.google.firebase.database.DataSnapshot;
9 | import com.google.firebase.database.DatabaseError;
10 | import com.google.firebase.database.DatabaseReference;
11 | import com.google.firebase.database.Query;
12 | import com.google.firebase.database.ValueEventListener;
13 |
14 | import org.junit.Before;
15 | import org.junit.Test;
16 | import org.mockito.ArgumentCaptor;
17 | import org.mockito.Mock;
18 | import org.mockito.MockitoAnnotations;
19 |
20 | import java.util.ArrayList;
21 | import java.util.Arrays;
22 | import java.util.Collections;
23 | import java.util.HashMap;
24 | import java.util.LinkedHashMap;
25 | import java.util.List;
26 | import java.util.Map;
27 |
28 | import durdinapps.rxfirebase2.exceptions.RxFirebaseDataException;
29 | import io.reactivex.functions.Function;
30 | import io.reactivex.observers.TestObserver;
31 | import io.reactivex.subscribers.TestSubscriber;
32 |
33 | import static durdinapps.rxfirebase2.RxTestUtil.ANY_KEY;
34 | import static durdinapps.rxfirebase2.RxTestUtil.PREVIOUS_CHILD_NAME;
35 | import static org.mockito.ArgumentMatchers.eq;
36 | import static org.mockito.Mockito.doReturn;
37 | import static org.mockito.Mockito.mock;
38 | import static org.mockito.Mockito.verify;
39 | import static org.mockito.Mockito.when;
40 |
41 | public class RxFirebaseDatabaseTest {
42 |
43 | @Mock
44 | private DatabaseReference databaseReference;
45 | @Mock
46 | private DatabaseReference databaseReferenceTwo;
47 |
48 | @Mock
49 | private Query query;
50 |
51 | @Mock
52 | private DataSnapshot dataSnapshot;
53 | @Mock
54 | private DataSnapshot dataSnapshotTwo;
55 |
56 | @Mock
57 | private Task voidTask;
58 |
59 | private ChildData childData = new ChildData();
60 | private List childDataList = new ArrayList<>();
61 | private Map childDataMap = new HashMap<>();
62 | private Map updatedData = new HashMap<>();
63 |
64 | private RxFirebaseChildEvent childEventAdded;
65 | private RxFirebaseChildEvent childEventChanged;
66 | private RxFirebaseChildEvent childEventRemoved;
67 | private RxFirebaseChildEvent childEventMoved;
68 |
69 | @Before
70 | public void setup() {
71 | MockitoAnnotations.initMocks(this);
72 |
73 | childDataList.add(childData);
74 | childDataMap.put(ANY_KEY, childData);
75 | updatedData.put(databaseReference.toString(), childData);
76 |
77 | childEventAdded = new RxFirebaseChildEvent<>(ANY_KEY, childData, PREVIOUS_CHILD_NAME, RxFirebaseChildEvent.EventType.ADDED);
78 | childEventChanged = new RxFirebaseChildEvent<>(ANY_KEY, childData, PREVIOUS_CHILD_NAME, RxFirebaseChildEvent.EventType.CHANGED);
79 | childEventRemoved = new RxFirebaseChildEvent<>(ANY_KEY, childData, RxFirebaseChildEvent.EventType.REMOVED);
80 | childEventMoved = new RxFirebaseChildEvent<>(ANY_KEY, childData, PREVIOUS_CHILD_NAME, RxFirebaseChildEvent.EventType.MOVED);
81 |
82 | when(dataSnapshot.exists()).thenReturn(true);
83 | when(dataSnapshot.getValue(ChildData.class)).thenReturn(childData);
84 | when(dataSnapshot.getKey()).thenReturn(ANY_KEY);
85 | when(dataSnapshot.getChildren()).thenReturn(Arrays.asList(dataSnapshot));
86 |
87 | when(dataSnapshotTwo.exists()).thenReturn(true);
88 | when(dataSnapshotTwo.getValue(ChildData.class)).thenReturn(childData);
89 | when(dataSnapshotTwo.getKey()).thenReturn(ANY_KEY);
90 | when(dataSnapshotTwo.getChildren()).thenReturn(Arrays.asList(dataSnapshotTwo));
91 |
92 | when(databaseReference.updateChildren(updatedData)).thenReturn(voidTask);
93 | }
94 |
95 | @Test
96 | public void testObserveSingleValue() {
97 | TestObserver testObserver = RxFirebaseDatabase
98 | .observeSingleValueEvent(databaseReference, ChildData.class)
99 | .test();
100 |
101 | ArgumentCaptor argument = ArgumentCaptor.forClass(ValueEventListener.class);
102 | verify(databaseReference).addListenerForSingleValueEvent(argument.capture());
103 | argument.getValue().onDataChange(dataSnapshot);
104 |
105 | testObserver.assertNoErrors()
106 | .assertValueCount(1)
107 | .assertValueSet(Collections.singletonList(childData))
108 | .assertComplete()
109 | .dispose();
110 | }
111 |
112 | @Test
113 | public void testObserveSingleNoData() {
114 |
115 | DataSnapshot mockFirebaseDataSnapshotNoData = mock(DataSnapshot.class);
116 | when(mockFirebaseDataSnapshotNoData.exists()).thenReturn(false);
117 |
118 | TestObserver testObserver = RxFirebaseDatabase
119 | .observeSingleValueEvent(databaseReference, ChildData.class)
120 | .test();
121 |
122 | ArgumentCaptor argument = ArgumentCaptor.forClass(ValueEventListener.class);
123 | verify(databaseReference).addListenerForSingleValueEvent(argument.capture());
124 | argument.getValue().onDataChange(mockFirebaseDataSnapshotNoData);
125 |
126 | testObserver.assertValueCount(0)
127 | .assertComplete()
128 | .dispose();
129 | }
130 |
131 | @Test
132 | public void testObserveSingleWrongType() {
133 |
134 | TestObserver testObserver = RxFirebaseDatabase
135 | .observeSingleValueEvent(databaseReference, WrongType.class)
136 | .test();
137 |
138 | ArgumentCaptor argument = ArgumentCaptor.forClass(ValueEventListener.class);
139 | verify(databaseReference).addListenerForSingleValueEvent(argument.capture());
140 | argument.getValue().onDataChange(dataSnapshot);
141 |
142 | testObserver.assertError(RuntimeException.class)
143 | .assertNotComplete()
144 | .dispose();
145 | }
146 |
147 | @Test
148 | public void testObserveSingleValueDisconnected() {
149 |
150 | TestObserver testObserver = RxFirebaseDatabase
151 | .observeSingleValueEvent(databaseReference, ChildData.class)
152 | .test();
153 |
154 | ArgumentCaptor