Skip to content

Commit

Permalink
Improve test coverage for Google suggestions source.
Browse files Browse the repository at this point in the history
  • Loading branch information
arunkumar9t2 committed Jun 3, 2018
1 parent 64d7de9 commit 23092f1
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,20 @@

package in.arunkumarsampath.suggestions2.source.google;

import android.text.TextUtils;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.FileNotFoundException;
import java.util.List;

import in.arunkumarsampath.suggestions2.Util;
import in.arunkumarsampath.suggestions2.item.SimpleSuggestionItem;
import io.reactivex.Flowable;
import io.reactivex.subscribers.TestSubscriber;

public class GoogleSuggestionSourceTest {

Expand All @@ -40,27 +49,62 @@ public void tearDown() {

@Test
public void getSuggestions() {
suggestionSource.getSuggestions("Hello")
.test(1)
.assertSubscribed()
.assertComplete()
.assertNoErrors();
Flowable<SimpleSuggestionItem> suggestions = suggestionSource.getSuggestions("Hello");
if (Util.isOnline()) {
suggestions.test(1)
.assertSubscribed()
.assertComplete()
.assertNoErrors();

suggestions.test(3)
.assertValueCount(3)
.assertComplete()
.assertNoErrors();
} else {
testFailureNoEvents(suggestions);
}
}

@Test
public void getSuggestionsFailure() {
suggestionSource.getSuggestions("")
.test()
.assertError(FileNotFoundException.class)
.assertNotComplete()
.assertNoValues();
Flowable<SimpleSuggestionItem> suggestions = suggestionSource.getSuggestions("");
if (Util.isOnline()) {
suggestions
.test()
.assertError(FileNotFoundException.class)
.assertNotComplete()
.assertNoValues();
} else {
testFailureNoEvents(suggestions);
}
}


@Test
public void getSuggestions_ValuesNotEmpty() {
suggestionSource.getSuggestions("Hello")
.test()
.assertComplete();
Flowable<SimpleSuggestionItem> suggestions = suggestionSource.getSuggestions("Hello");

if (Util.isOnline()) {
final TestSubscriber<SimpleSuggestionItem> suggestionItemTestSubscriber = suggestions.test();
suggestionItemTestSubscriber
.assertNoErrors()
.assertComplete();

final List<List<Object>> events = suggestionItemTestSubscriber.getEvents();
final List<Object> onNextEvents = events.get(0);
for (Object suggestionItem : onNextEvents) {
Assert.assertTrue(suggestionItem instanceof SimpleSuggestionItem);
Assert.assertNotNull(((SimpleSuggestionItem) suggestionItem).value());
Assert.assertTrue(!TextUtils.isEmpty(((SimpleSuggestionItem) suggestionItem).value()));
}
} else {
testFailureNoEvents(suggestions);
}
}

private void testFailureNoEvents(Flowable<SimpleSuggestionItem> suggestions) {
suggestions.test()
.assertNoValues()
.assertNotComplete();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
/**
* Simple {@link SuggestionItem} that holds a {@link String}
*/
public class StringSuggestionItem implements SuggestionItem<String> {
public class SimpleSuggestionItem implements SuggestionItem<String> {

@NonNull
private final String value;

public StringSuggestionItem(@NonNull String value) {
public SimpleSuggestionItem(@NonNull String value) {
this.value = value;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@
* Suggestions source is the definition for a class that provides suggestions for a given string.
* <p>
* To enable functionality override {@link #getSuggestions(String)}, add your suggestion logic
* and return a {@link Flowable<SuggestionItem>}
* and return a {@link Flowable}
* <p>
* {@link #getSuggestions(String)} can be called repeatedly in any order. If stateful code is added,
* be sure to handle it correctly for each invocation.
*/
public interface SuggestionSource {
public interface SuggestionSource<T extends SuggestionItem> {

@NonNull
Flowable<SuggestionItem> getSuggestions(@NonNull final String value);
Flowable<T> getSuggestions(@NonNull final String value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
import java.net.HttpURLConnection;
import java.net.URL;

import in.arunkumarsampath.suggestions2.item.StringSuggestionItem;
import in.arunkumarsampath.suggestions2.item.SuggestionItem;
import in.arunkumarsampath.suggestions2.item.SimpleSuggestionItem;
import in.arunkumarsampath.suggestions2.source.SuggestionSource;
import in.arunkumarsampath.suggestions2.util.Util;
import io.reactivex.BackpressureStrategy;
Expand All @@ -40,19 +39,18 @@
/**
* A suggestion source backed by Google suggest API.
*/
public class GoogleSuggestionSource implements SuggestionSource {
public final class GoogleSuggestionSource implements SuggestionSource<SimpleSuggestionItem> {

private static final String SUGGEST_URL_FORMAT = "http://suggestqueries.google.com/complete/search?client=toolbar&q=%s";
private static final String SUGGESTION = "suggestion";

@NonNull
@Override
public Flowable<SuggestionItem> getSuggestions(@NonNull String value) {
public Flowable<SimpleSuggestionItem> getSuggestions(@NonNull String value) {
return Flowable.fromCallable(() -> {
HttpURLConnection httpURLConnection;
final String suggestUrl = String.format(SUGGEST_URL_FORMAT, Util.prepareSearchTerm(value));
final URL url = new URL(suggestUrl);
httpURLConnection = (HttpURLConnection) url.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.connect();
return httpURLConnection;
}).flatMap(httpURLConnection -> Flowable.create(emitter -> {
Expand All @@ -66,7 +64,7 @@ public Flowable<SuggestionItem> getSuggestions(@NonNull String value) {
boolean validEvent = eventType == START_TAG && xmlParser.getName().equalsIgnoreCase(SUGGESTION);
if (validEvent) {
final String suggestion = xmlParser.getAttributeValue(0);
emitter.onNext(new StringSuggestionItem(suggestion));
emitter.onNext(new SimpleSuggestionItem(suggestion));
}
eventType = xmlParser.next();
}
Expand All @@ -81,14 +79,17 @@ public Flowable<SuggestionItem> getSuggestions(@NonNull String value) {
/**
* Method to check if XML iteration can be still performed.
* <p>
* Checks if {@link Flowable} is still valid, if downstream is actively requesting further elements,
* and we have not reached XML document end.
* Checks if {@link Flowable} is still valid based on:
* <ul>
* <li>Downstream is actively requesting further elements.</li>
* <li>XML document end has not reached.</li>
* </ul>
*
* @param emitter The emitter to currently handling events.
* @param eventType XML document event type.
* @return {@code true} if Flowable emission is valid.
*/
private boolean isFlowableEmissionValid(FlowableEmitter<SuggestionItem> emitter, int eventType) {
private boolean isFlowableEmissionValid(FlowableEmitter<SimpleSuggestionItem> emitter, int eventType) {
return eventType != END_DOCUMENT && !emitter.isCancelled() && emitter.requested() > 0;
}

Expand Down

0 comments on commit 23092f1

Please sign in to comment.