blob: 3ae2f6d4aec729c04fda62c00a2c6fa6920495e0 [file] [log] [blame]
// Copyright 2018 The Feed Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.android.libraries.feed.feedknowncontent;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import com.google.android.libraries.feed.api.common.ThreadUtils;
import com.google.android.libraries.feed.api.knowncontent.ContentMetadata;
import com.google.android.libraries.feed.api.knowncontent.ContentRemoval;
import com.google.android.libraries.feed.api.knowncontent.KnownContentApi.KnownContentListener;
import com.google.android.libraries.feed.api.sessionmanager.SessionManager;
import com.google.android.libraries.feed.common.Result;
import com.google.android.libraries.feed.common.concurrent.testing.FakeMainThreadRunner;
import com.google.android.libraries.feed.common.functional.Consumer;
import com.google.android.libraries.feed.common.functional.Function;
import com.google.search.now.feed.client.StreamDataProto.StreamFeature;
import com.google.search.now.feed.client.StreamDataProto.StreamPayload;
import com.google.search.now.ui.stream.StreamStructureProto.Content;
import com.google.search.now.ui.stream.StreamStructureProto.OfflineMetadata;
import com.google.search.now.ui.stream.StreamStructureProto.RepresentationData;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link FeedKnownContentApi}. */
@RunWith(RobolectricTestRunner.class)
public class FeedKnownContentApiTest {
private static final long CONTENT_CREATION_DATE_TIME_MS = 123L;
private static final List<ContentRemoval> CONTENT_REMOVED =
Collections.singletonList(new ContentRemoval("url", /* requestedByUser= */ false));
private static final String URL = "url";
private static final String TITLE = "title";
@Mock private SessionManager sessionManager;
@Mock private KnownContentListener listener1;
@Mock private KnownContentListener listener2;
@Mock private Consumer<List<ContentMetadata>> knownContentConsumer;
@Mock private ThreadUtils threadUtils;
private final FakeMainThreadRunner mainThreadRunner = FakeMainThreadRunner.runTasksImmediately();
@Captor
private ArgumentCaptor<Function<StreamPayload, ContentMetadata>> knownContentFunctionCaptor;
@Captor
private ArgumentCaptor<Consumer<Result<List<ContentMetadata>>>> contentMetadataResultCaptor;
private FeedKnownContentApi knownContentApi;
@Before
public void setUp() {
initMocks(this);
when(threadUtils.isMainThread()).thenReturn(true);
knownContentApi = new FeedKnownContentApi(sessionManager, mainThreadRunner, threadUtils);
}
@Test
public void testSetsListenerOnSessionManager() {
verify(sessionManager).setKnownContentListener(knownContentApi.getKnownContentHostNotifier());
}
@Test
public void testNotifyListeners_contentReceived() {
knownContentApi.addListener(listener1);
knownContentApi.addListener(listener2);
knownContentApi
.getKnownContentHostNotifier()
.onNewContentReceived(/* isNewRefresh= */ false, CONTENT_CREATION_DATE_TIME_MS);
verify(listener1)
.onNewContentReceived(/* isNewRefresh= */ false, CONTENT_CREATION_DATE_TIME_MS);
verify(listener2)
.onNewContentReceived(/* isNewRefresh= */ false, CONTENT_CREATION_DATE_TIME_MS);
}
@Test
public void testNotifyListeners_contentRemoved() {
knownContentApi.addListener(listener1);
knownContentApi.addListener(listener2);
knownContentApi.getKnownContentHostNotifier().onContentRemoved(CONTENT_REMOVED);
verify(listener1).onContentRemoved(CONTENT_REMOVED);
verify(listener2).onContentRemoved(CONTENT_REMOVED);
}
@Test
public void testRemoveListener() {
knownContentApi.addListener(listener1);
knownContentApi.removeListener(listener1);
knownContentApi.getKnownContentHostNotifier().onContentRemoved(CONTENT_REMOVED);
knownContentApi
.getKnownContentHostNotifier()
.onNewContentReceived(/* isNewRefresh= */ true, CONTENT_CREATION_DATE_TIME_MS);
verifyNoMoreInteractions(listener1);
}
@Test
public void testGetKnownContent_returnsNullForNonContent() {
knownContentApi.getKnownContent(knownContentConsumer);
verify(sessionManager)
.getStreamFeaturesFromHead(
knownContentFunctionCaptor.capture(), contentMetadataResultCaptor.capture());
assertThat(knownContentFunctionCaptor.getValue().apply(StreamPayload.getDefaultInstance()))
.isNull();
}
@Test
public void testGetKnownContent_returnsContentMetadataFromContent() {
knownContentApi.getKnownContent(knownContentConsumer);
verify(sessionManager)
.getStreamFeaturesFromHead(
knownContentFunctionCaptor.capture(), contentMetadataResultCaptor.capture());
StreamPayload streamPayload =
StreamPayload.newBuilder()
.setStreamFeature(
StreamFeature.newBuilder()
.setContent(
Content.newBuilder()
.setOfflineMetadata(OfflineMetadata.newBuilder().setTitle(TITLE))
.setRepresentationData(RepresentationData.newBuilder().setUri(URL))))
.build();
ContentMetadata contentMetadata = knownContentFunctionCaptor.getValue().apply(streamPayload);
assertThat(contentMetadata.getUrl()).isEqualTo(URL);
assertThat(contentMetadata.getTitle()).isEqualTo(TITLE);
}
@Test
public void testGetKnownContent_failure() {
knownContentApi.getKnownContent(knownContentConsumer);
verify(sessionManager)
.getStreamFeaturesFromHead(
knownContentFunctionCaptor.capture(), contentMetadataResultCaptor.capture());
contentMetadataResultCaptor.getValue().accept(Result.failure());
verify(knownContentConsumer, never()).accept(Mockito.<List<ContentMetadata>>any());
}
@Test
public void testGetKnownContent_offMainThread() {
FakeMainThreadRunner fakeMainThreadRunner = FakeMainThreadRunner.queueAllTasks();
when(threadUtils.isMainThread()).thenReturn(false);
knownContentApi = new FeedKnownContentApi(sessionManager, fakeMainThreadRunner, threadUtils);
knownContentApi.addListener(listener1);
knownContentApi
.getKnownContentHostNotifier()
.onNewContentReceived(/* isNewRefresh= */ false, CONTENT_CREATION_DATE_TIME_MS);
assertThat(fakeMainThreadRunner.hasTasks()).isTrue();
verifyZeroInteractions(listener1);
fakeMainThreadRunner.runAllTasks();
verify(listener1)
.onNewContentReceived(/* isNewRefresh= */ false, CONTENT_CREATION_DATE_TIME_MS);
}
}