package org.wikipedia.page.leadimages;
import android.graphics.PointF;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import com.facebook.testing.screenshot.ViewHelpers;
import org.junit.Test;
import org.junit.experimental.theories.Theory;
import org.junit.experimental.theories.suppliers.TestedOn;
import org.wikipedia.Constants;
import org.wikipedia.page.leadimages.PageHeaderView.Callback;
import org.wikipedia.test.theories.TestedOnBool;
import org.wikipedia.test.view.FontScale;
import org.wikipedia.test.view.LayoutDirection;
import org.wikipedia.test.view.PrimaryTestImg;
import org.wikipedia.test.view.PrimaryTestStr;
import org.wikipedia.test.view.SecondaryTestImg;
import org.wikipedia.test.view.SecondaryTestStr;
import org.wikipedia.test.view.TestImg;
import org.wikipedia.test.view.TestStr;
import org.wikipedia.test.view.ViewTest;
import org.wikipedia.theme.Theme;
import org.wikipedia.views.FaceAndColorDetectImageView.OnImageLoadListener;
import static org.apache.commons.lang3.StringUtils.defaultIfEmpty;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.startsWith;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.wikipedia.test.TestUtil.runOnMainSync;
public class PageHeaderViewTest extends ViewTest {
private PageHeaderView subject;
@Theory public void testLayout(@TestedOn(ints = {WIDTH_DP_L, WIDTH_DP_M}) int widthDp,
// @TestedOn(ints = {HEIGHT_DP_L, WIDTH_DP_S}) int heightDp,
@NonNull FontScale fontScale, @NonNull PrimaryTestImg image,
@NonNull PrimaryTestStr title, @NonNull SecondaryTestStr subtitle,
@TestedOnBool boolean pronunciation) {
// todo: pass height when layout is correct
setUp(widthDp, 0, LayoutDirection.LOCALE, fontScale, Theme.LIGHT, image, title,
subtitle, pronunciation);
snap(subject, image + "_image", title + "_title", subtitle + "_subtitle",
pronunciation ? "pronunciation" : "no_pronunciation");
}
@Theory public void testLayoutDirection(@NonNull LayoutDirection direction) {
setUp(WIDTH_DP_L, HEIGHT_DP_L, direction, FontScale.DEFAULT, Theme.LIGHT,
PrimaryTestImg.NONNULL, PrimaryTestStr.SHORT, PrimaryTestStr.SHORT, true);
subject.setLocale(direction.isRtl() ? "he" : LOCALES[0].getLanguage());
snap(subject);
}
@Theory public void testTheme(@NonNull Theme theme) {
setUp(WIDTH_DP_L, HEIGHT_DP_L, LayoutDirection.LOCALE, FontScale.DEFAULT, theme,
PrimaryTestImg.NONNULL, PrimaryTestStr.SHORT, PrimaryTestStr.SHORT, true);
snap(subject);
}
@Test public void testHide() {
setUpTypical();
subject.hide();
assertThat(subject.getVisibility(), is(View.GONE));
}
@Test public void testShowTextTitleContent() {
setUpTypical();
String text = "text";
setTitle(text);
showText();
assertThat(subject.titleText.getText().toString(), startsWith(text));
}
@Theory public void testShowTextSubtitleContent(@TestedOnBool boolean nul) {
setUpTypical();
String text = nul ? null : "text";
setSubtitle(text);
showText();
assertThat(subject.subtitleText.getText().length(), greaterThan(0));
if (text != null) {
// null case uses placeholder text
assertThat(subject.subtitleText.getText().toString(), is(text));
}
}
@Theory public void testShowTextVisible(@TestedOnBool boolean afterHide) {
setUpTypical();
if (afterHide) {
subject.hide();
}
showText();
assertThat(subject.getVisibility(), is(View.VISIBLE));
assertThat(subject.statusBarPlaceholder.getVisibility(), is(View.VISIBLE));
}
@Theory public void testShowTextImageVisible(@TestedOnBool boolean afterHide) {
setUpTypical();
if (afterHide) {
subject.hide();
}
showTextImage();
assertThat(subject.getVisibility(), is(View.VISIBLE));
assertThat(subject.statusBarPlaceholder.getVisibility(), is(View.GONE));
}
@Theory public void testGetImage(@TestedOnBool boolean nul) {
setUpTypical();
String url = nul ? null : frescoUri(SecondaryTestImg.CHECKERBOARD.id()).toString();
subject.loadImage(url);
assertThat(subject.getImage(), notNullValue());
}
@Theory public void testSetOnImageLoadListener(@TestedOnBool boolean nul,
@TestedOnBool final boolean fail) {
setUpTypical();
OnImageLoadListener listener = nul ? null : mock(OnImageLoadListener.class);
subject.setOnImageLoadListener(listener);
String url = fail ? "http://" : frescoUri(SecondaryTestImg.CHECKERBOARD.id()).toString();
subject.loadImage(url);
// todo: wait for image to load and verify
// if (listener != null) {
// if (fail) {
// verify(listener, never()).onImageLoaded(anyInt(), any(PointF.class), anyInt());
// verify(listener).onImageFailed();
// } else {
// verify(listener).onImageLoaded(anyInt(), any(PointF.class), anyInt());
// verify(listener, never()).onImageFailed();
// }
// }
}
@Theory public void testSetCallback(@TestedOnBool boolean nul,
@TestedOnBool boolean descriptionClicked) {
setUpTypical();
Callback callback = nul ? null : mock(Callback.class);
subject.setCallback(callback);
if (descriptionClicked) {
subject.descriptionClickSpan.onClick(subject);
} else {
// todo: how to test activity?
// subject.editPencil.performClick();
}
if (callback != null) {
if (descriptionClicked) {
verify(callback).onDescriptionClicked();
verify(callback, never()).onEditDescription();
verify(callback, never()).onEditLeadSection();
} else {
verify(callback, never()).onDescriptionClicked();
verify(callback, never()).onEditDescription();
// todo: how to test activity?
// verify(callback).onEditLeadSection();
}
}
}
@Theory public void testLoadImage(@TestedOnBool boolean nul) {
setUpTypical();
String url = nul ? null : frescoUri(SecondaryTestImg.CHECKERBOARD.id()).toString();
subject.loadImage(url);
assertThat(subject.getMinimumHeight(), nul ? is(0) : greaterThan(0));
}
@Theory public void testSetAnimationPaused(@TestedOnBool boolean nul,
@TestedOnBool boolean paused) {
setUpTypical();
String url = nul ? null : frescoUri(SecondaryTestImg.CHECKERBOARD.id()).toString();
subject.loadImage(url);
subject.setAnimationPaused(paused);
if (!nul) {
// todo: wait for image to load and verify
// assertThat(subject.image.getImage().getController().getAnimatable().isRunning(), is(paused));
}
}
@Test public void testCopyBitmap() {
setUpTypical();
// width and height must be > 0 for Bitmap.createBitmap()
final int positive = 100;
ViewHelpers.setupView(subject).setExactWidthDp(positive).setExactHeightDp(positive).layout();
runOnMainSync(new Runnable() {
@Override public void run() {
assertThat(subject.copyBitmap(), notNullValue());
}
});
}
@Test public void testSetImageFocus() {
setUpTypical();
subject.setImageFocus(new PointF());
// todo: verify
}
@Theory public void testSetTitle(@TestedOnBool boolean nul) {
setUpTypical();
CharSequence text = nul ? null : "text";
setTitle(text);
assertThat(subject.title, is(defaultIfEmpty(text, "")));
}
@Theory public void testSetSubtitle(@TestedOnBool boolean nul) {
setUpTypical();
CharSequence text = nul ? null : "text";
setSubtitle(text);
assertThat(subject.subtitle, is(defaultIfEmpty(text, "")));
}
@Theory public void testHasSubtitle(@TestedOnBool boolean nul) {
setUpTypical();
setSubtitle(nul ? null : "text");
assertThat(subject.hasSubtitle(), is(!nul));
}
@Test public void testSetLocale() {
setUpTypical();
subject.setLocale(LOCALES[0].getLanguage());
// todo: how to verify?
}
@Theory public void testSetPronunciation(@TestedOnBool boolean nul) {
setUpTypical();
String url = nul ? null : Constants.WIKIPEDIA_URL;
setPronunciation(url);
assertThat(subject.pronunciationUrl, is(url));
}
@Theory public void testHasPronunciation(@TestedOnBool boolean nul) {
setUpTypical();
setPronunciation(nul ? null : Constants.WIKIPEDIA_URL);
assertThat(subject.hasPronunciation(), is(!nul));
}
@Theory public void testOnScrollChanged(@TestedOn(ints = {-1, 0, 1}) int y) {
setUpTypical();
// width and height must be > 0 for Bitmap.createBitmap()
final int height = 100;
ViewHelpers.setupView(subject).setExactHeightDp(height).layout();
subject.onScrollChanged(0, y, false);
assertThat((int) subject.getTranslationY(), is(-Math.min(height, y)));
assertThat((int) subject.image.getImage().getTranslationY(), is(y / 2));
}
private void showText() {
runOnMainSync(new Runnable() {
@Override public void run() {
subject.showText();
}
});
}
private void showTextImage() {
runOnMainSync(new Runnable() {
@Override public void run() {
subject.showTextImage();
}
});
}
private void setTitle(@Nullable final CharSequence text) {
runOnMainSync(new Runnable() {
@Override public void run() {
subject.setTitle(text);
}
});
}
private void setSubtitle(@Nullable final CharSequence text) {
runOnMainSync(new Runnable() {
@Override public void run() {
subject.setSubtitle(text);
}
});
}
private void setPronunciation(@Nullable final String url) {
runOnMainSync(new Runnable() {
@Override public void run() {
subject.setPronunciation(url);
}
});
}
private void setUpTypical() {
setUp(WIDTH_DP_M, HEIGHT_DP_M, LayoutDirection.LOCALE, FontScale.DEFAULT, Theme.LIGHT,
PrimaryTestImg.NONNULL, PrimaryTestStr.LONG, SecondaryTestStr.LONG, true);
}
@SuppressWarnings("checkstyle:parameternumber")
private void setUp(int widthDp, int heightDp, @NonNull LayoutDirection layoutDirection,
@NonNull FontScale fontScale, @NonNull Theme theme, @NonNull TestImg image,
@NonNull TestStr title, @NonNull TestStr subtitle,
final boolean pronunciation) {
// todo: pass height
//setUp(widthDp, heightDp, layoutDirection, fontScale, theme);
setUp(widthDp, layoutDirection, fontScale, theme);
Uri imageUri = frescoUri(image.id());
subject = new PageHeaderView(ctx());
subject.loadImage(imageUri == null ? null : imageUri.toString());
setTitle(str(title));
setSubtitle(str(subtitle));
subject.setLocale(LOCALES[0].getLanguage());
setPronunciation(pronunciation ? Constants.WIKIPEDIA_URL : null);
}
}