package com.novoda.bonfire.channel.database; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.novoda.bonfire.channel.data.model.Channel; import com.novoda.bonfire.rx.FirebaseObservableListeners; import com.novoda.bonfire.user.data.model.User; import java.util.Arrays; import java.util.List; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import rx.Observable; import static com.novoda.bonfire.helpers.FirebaseTestHelpers.*; import static org.mockito.Matchers.any; import static org.mockito.Mockito.anyObject; import static org.mockito.Mockito.when; public class FirebaseChannelsDatabaseTest { private final User user = new User("user id", "user", "http://photo"); private final Channel newChannel = new Channel("new channel", Channel.Access.PUBLIC); private final List<String> publicChannelIds = Arrays.asList("first public id", "second public id"); private final List<String> privateChannelIds = Arrays.asList("first private id", "second private id"); private final List<String> ownerIds = Arrays.asList("first owner id", "second owner id"); @Mock DatabaseReference mockPublicChannelsDb; @Mock DatabaseReference mockPrivateChannelsDb; @Mock DatabaseReference mockChannelsDb; @Mock DatabaseReference mockOwnersDb; @Mock FirebaseDatabase mockFirebaseDatabase; @Mock FirebaseObservableListeners mockListeners; FirebaseChannelsDatabase firebaseChannelsDatabase; @Before public void setup() { MockitoAnnotations.initMocks(this); setupDatabaseStubsFor("public-channels-index", mockPublicChannelsDb, mockFirebaseDatabase); setupDatabaseStubsFor("private-channels-index", mockPrivateChannelsDb, mockFirebaseDatabase); setupDatabaseStubsFor("channels", mockChannelsDb, mockFirebaseDatabase); setupDatabaseStubsFor("owners", mockOwnersDb, mockFirebaseDatabase); setupValueEventListenerFor(mockListeners, mockPublicChannelsDb, publicChannelIds); setupValueEventListenerFor(mockListeners, mockPrivateChannelsDb, privateChannelIds); setupValueEventListenerFor(mockListeners, mockOwnersDb, ownerIds); setupValueEventListenerFor(mockListeners, mockPrivateChannelsDb, privateChannelIds); setupValueEventListenerFor(mockListeners, mockOwnersDb, ownerIds); setupSingleValueEventListenerFor(mockListeners, mockChannelsDb, newChannel); when(mockListeners.setValue(anyObject(), any(DatabaseReference.class), any(Channel.class))).thenReturn(Observable.just(newChannel)); when(mockListeners.removeValue(any(DatabaseReference.class), any(Channel.class))).thenReturn(Observable.just(newChannel)); firebaseChannelsDatabase = new FirebaseChannelsDatabase(mockFirebaseDatabase, mockListeners); } @Test public void publicChannelsIdsAreObservedFromPublicChannelDatabase() { Observable<List<String>> listObservable = firebaseChannelsDatabase.observePublicChannelIds(); assertValueReceivedOnNext(listObservable, publicChannelIds); } @Test public void onErrorIsCalledWhenPublicChannelIdsCannotBeObserved() { Throwable testThrowable = new Throwable("test throwable"); setupErroringValueEventListenerFor(mockListeners, mockPublicChannelsDb, testThrowable); Observable<List<String>> listObservable = firebaseChannelsDatabase.observePublicChannelIds(); assertThrowableReceivedOnError(listObservable, testThrowable); } @Test public void privateChannelsIdsForAUserAreObservedFromPrivateChannelDatabase() { Observable<List<String>> listObservable = firebaseChannelsDatabase.observePrivateChannelIdsFor(user); assertValueReceivedOnNext(listObservable, privateChannelIds); } @Test public void onErrorIsCalledWhenPrivateChannelIdsCannotBeObserved() { Throwable testThrowable = new Throwable("test throwable"); setupErroringValueEventListenerFor(mockListeners, mockPrivateChannelsDb, testThrowable); Observable<List<String>> listObservable = firebaseChannelsDatabase.observePrivateChannelIdsFor(user); assertThrowableReceivedOnError(listObservable, testThrowable); } @Test public void channelDetailsAreReadFromChannelsDatabase() { Observable<Channel> channelObservable = firebaseChannelsDatabase.readChannelFor("new channel"); assertValueReceivedOnNext(channelObservable, newChannel); } @Test public void canSetNewChannelInChannelsDatabaseAndReturnIt() { Observable<Channel> channelObservable = firebaseChannelsDatabase.writeChannel(newChannel); assertValueReceivedOnNext(channelObservable, newChannel); } @Test public void canSetNewChannelInPublicChannelDatabaseAndReturnIt() { Observable<Channel> channelObservable = firebaseChannelsDatabase.writeChannelToPublicChannelIndex(newChannel); assertValueReceivedOnNext(channelObservable, newChannel); } @Test public void newChannelIsSetForUserInOwnersDatabase() { Observable<Channel> channelObservable = firebaseChannelsDatabase.addOwnerToPrivateChannel(user, newChannel); assertValueReceivedOnNext(channelObservable, newChannel); } @Test public void channelCanBeRemovedFromOwnersDatabase() { Observable<Channel> channelObservable = firebaseChannelsDatabase.removeOwnerFromPrivateChannel(user, newChannel); assertValueReceivedOnNext(channelObservable, newChannel); } @Test public void canAddChannelToPrivateChannelDatabaseForUser() { Observable<Channel> channelObservable = firebaseChannelsDatabase.addChannelToUserPrivateChannelIndex(user, newChannel); assertValueReceivedOnNext(channelObservable, newChannel); } @Test public void canRemoveChannelFromPrivateChannelDatabaseForUser() { Observable<Channel> channelObservable = firebaseChannelsDatabase.removeChannelFromUserPrivateChannelIndex(user, newChannel); assertValueReceivedOnNext(channelObservable, newChannel); } @Test public void canGetOwnerIdsForAChannelFromOwnersDatabase() { Observable<List<String>> listObservable = firebaseChannelsDatabase.observeOwnerIdsFor(newChannel); assertValueReceivedOnNext(listObservable, ownerIds); } @Test public void onErrorIsCalledWhenOwnerIdsCannotBeObserved() { Throwable testThrowable = new Throwable("test throwable"); setupErroringValueEventListenerFor(mockListeners, mockOwnersDb, testThrowable); Observable<List<String>> listObservable = firebaseChannelsDatabase.observeOwnerIdsFor(newChannel); assertThrowableReceivedOnError(listObservable, testThrowable); } }