package com.vaguehope.onosendai.provider.twitter;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.net.ssl.SSLException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import twitter4j.HttpResponse;
import twitter4j.MediaEntity;
import twitter4j.MediaEntity.Variant;
import twitter4j.Status;
import twitter4j.TwitterException;
import twitter4j.URLEntity;
import twitter4j.User;
import twitter4j.UserMentionEntity;
import com.vaguehope.onosendai.config.Account;
import com.vaguehope.onosendai.model.Meta;
import com.vaguehope.onosendai.model.MetaType;
import com.vaguehope.onosendai.model.Tweet;
import com.vaguehope.onosendai.util.CollectionHelper;
@RunWith(RobolectricTestRunner.class)
public class TwitterUtilsTest {
private Account account;
@Before
public void before () throws Exception {
this.account = mock(Account.class);
}
@Test
public void itAddsExtraMetas () throws Exception {
final Status s = mockTweet("foo");
final Tweet t = TwitterUtils.convertTweet(this.account, s, -1L, false, CollectionHelper.listOf(new Meta(MetaType.FEED_HASH, "abcdefgh")), null);
assertThat(t.getMetas(), hasItem(new Meta(MetaType.FEED_HASH, "abcdefgh")));
assertThat(t.getMetas(), hasSize(2));
}
@Test
public void itExpandsUrl () {
final Status s = mockTweet("Got some fancy Nespresso from @noriko_hamada this morning. Approve. \ud83d\ude34\u2615\ufe0f\ud83d\udc4c https://t.co/9JdtE36Djy");
final URLEntity ue = mock(URLEntity.class);
when(ue.getExpandedURL()).thenReturn("http://twitter.com/stuarthicks/status/698806076515479552/photo/1");
when(ue.getURL()).thenReturn("https://t.co/9JdtE36Djy");
when(ue.getStart()).thenReturn(73);
when(ue.getEnd()).thenReturn(96);
when(s.getURLEntities()).thenReturn(new URLEntity[] { ue });
final Tweet t = TwitterUtils.convertTweet(this.account, s, -1L, false);
assertEquals("Got some fancy Nespresso from @noriko_hamada this morning. Approve. \ud83d\ude34\u2615\ufe0f\ud83d\udc4c http://twitter.com/stuarthicks/status/698806076515479552/photo/1", t.getBody());
}
@Test
public void itExpandsTwitterMedia () throws Exception {
final Status s = mockTweetWithMedia("https://twitter.com/some*user/status/1235430985/photo/1", "https://pbs.twimg.com/media/BjwsdkfjsAAI-4x.jpg");
final Tweet t = TwitterUtils.convertTweet(this.account, s, -1L, false);
assertThat(t.getMetas(), hasItem(new Meta(MetaType.MEDIA, "https://pbs.twimg.com/media/BjwsdkfjsAAI-4x.jpg", "https://twitter.com/some*user/status/1235430985/photo/1")));
assertEquals("media: ", t.getBody());
assertNoMetaOfType(t, MetaType.URL);
}
@Test
public void itExpandsTwitterTwoMedias () throws Exception {
final Status s = mockTweet("media.");
final MediaEntity me1 = mockMediaEntry("https://twitter.com/some*user/status/1235430985/photo/1", "https://pbs.twimg.com/media/BjwsdkfjsAAI-4x.jpg");
final MediaEntity me2 = mockMediaEntry("https://twitter.com/some*user/status/1235430986/photo/1", "https://pbs.twimg.com/media/BjwsdkfjsAAJ-4y.jpg");
when(s.getMediaEntities()).thenReturn(new MediaEntity[] { me1, me2 });
final Tweet t = TwitterUtils.convertTweet(this.account, s, -1L, false);
assertThat(t.getMetas(), hasItem(new Meta(MetaType.MEDIA, "https://pbs.twimg.com/media/BjwsdkfjsAAI-4x.jpg", "https://twitter.com/some*user/status/1235430985/photo/1")));
assertThat(t.getMetas(), hasItem(new Meta(MetaType.MEDIA, "https://pbs.twimg.com/media/BjwsdkfjsAAJ-4y.jpg", "https://twitter.com/some*user/status/1235430986/photo/1")));
assertNoMetaOfType(t, MetaType.URL);
assertEquals("2 pictures", t.getUserSubtitle());
}
@Test
public void itExpandsTwitterGif () throws Exception {
final Status s = mockTweet("media.");
final MediaEntity me1 = mockMediaEntry("https://twitter.com/some*user/status/1235430985/photo/1", "https://pbs.twimg.com/tweet_video_thumb/CEphgfeWAAEBurm.png");
final Variant v1 = mock(Variant.class);
when(s.getMediaEntities()).thenReturn(new MediaEntity[] { me1 });
when(me1.getType()).thenReturn("animated_gif");
when(me1.getVideoDurationMillis()).thenReturn(0L);
when(me1.getVideoVariants()).thenReturn(new Variant[] { v1 });
when(v1.getContentType()).thenReturn("video/mp4");
when(v1.getUrl()).thenReturn("https://pbs.twimg.com/tweet_video/CEphgfeWAAEBurm.mp4");
final Tweet t = TwitterUtils.convertTweet(this.account, s, -1L, false);
assertThat(t.getMetas(), hasItem(new Meta(MetaType.MEDIA, "https://pbs.twimg.com/tweet_video_thumb/CEphgfeWAAEBurm.png", "https://twitter.com/some*user/status/1235430985/photo/1")));
assertThat(t.getMetas(), hasItem(new Meta(MetaType.URL, "https://pbs.twimg.com/tweet_video/CEphgfeWAAEBurm.mp4", "video/mp4")));
assertEquals("gif", t.getUserSubtitle());
}
@Test
public void itExpandsTwitterVideo () throws Exception {
final Status s = mockTweet("media.");
final MediaEntity me1 = mockMediaEntry("http://twitter.com/twitter/status/560070183650213889/video/1", "https://pbs.twimg.com/ext_tw_video_thumb/560070131976392705/pu/img/TcG_ep5t-iqdLV5R.jpg");
final Variant v1 = mock(Variant.class);
final Variant v2 = mock(Variant.class);
final Variant v3 = mock(Variant.class);
final Variant v4 = mock(Variant.class);
final Variant v5 = mock(Variant.class);
when(s.getMediaEntities()).thenReturn(new MediaEntity[] { me1 });
when(me1.getType()).thenReturn("video");
when(me1.getVideoDurationMillis()).thenReturn(30033L);
when(me1.getVideoVariants()).thenReturn(new Variant[] { v1, v2, v3, v4, v5 });
when(v1.getContentType()).thenReturn("video/mp4");
when(v1.getBitrate()).thenReturn(2176000);
when(v1.getUrl()).thenReturn("https://video.twimg.com/ext_tw_video/560070131976392705/pu/vid/1280x720/c4E56sl91ZB7cpYi.mp4");
when(v2.getContentType()).thenReturn("video/mp4");
when(v2.getBitrate()).thenReturn(320000);
when(v2.getUrl()).thenReturn("https://video.twimg.com/ext_tw_video/560070131976392705/pu/vid/320x180/nXXsvs7vOhcMivwl.mp4");
when(v3.getContentType()).thenReturn("video/webm");
when(v3.getBitrate()).thenReturn(832000);
when(v3.getUrl()).thenReturn("https://video.twimg.com/ext_tw_video/560070131976392705/pu/vid/640x360/vmLr5JlVs2kBLrXS.webm");
when(v4.getContentType()).thenReturn("video/mp4");
when(v4.getBitrate()).thenReturn(832000);
when(v4.getUrl()).thenReturn("https://video.twimg.com/ext_tw_video/560070131976392705/pu/vid/640x360/vmLr5JlVs2kBLrXS.mp4");
when(v5.getContentType()).thenReturn("application/x-mpegURL");
when(v5.getUrl()).thenReturn("https://video.twimg.com/ext_tw_video/560070131976392705/pu/pl/r1kgzh5PmLgium3-.m3u8");
final Tweet t = TwitterUtils.convertTweet(this.account, s, -1L, false);
assertThat(t.getMetas(), hasItem(new Meta(MetaType.MEDIA, "https://pbs.twimg.com/ext_tw_video_thumb/560070131976392705/pu/img/TcG_ep5t-iqdLV5R.jpg", "http://twitter.com/twitter/status/560070183650213889/video/1")));
assertThat(t.getMetas(), hasItem(new Meta(MetaType.URL, "https://video.twimg.com/ext_tw_video/560070131976392705/pu/vid/1280x720/c4E56sl91ZB7cpYi.mp4", "video/mp4 0:30 2.1 MB/s")));
assertThat(t.getMetas(), hasItem(new Meta(MetaType.URL, "https://video.twimg.com/ext_tw_video/560070131976392705/pu/vid/320x180/nXXsvs7vOhcMivwl.mp4", "video/mp4 0:30 312.5 KB/s")));
assertThat(t.getMetas(), hasItem(new Meta(MetaType.URL, "https://video.twimg.com/ext_tw_video/560070131976392705/pu/vid/640x360/vmLr5JlVs2kBLrXS.webm", "video/webm 0:30 812.5 KB/s")));
assertThat(t.getMetas(), hasItem(new Meta(MetaType.URL, "https://video.twimg.com/ext_tw_video/560070131976392705/pu/vid/640x360/vmLr5JlVs2kBLrXS.mp4", "video/mp4 0:30 812.5 KB/s")));
assertThat(t.getMetas(), hasItem(new Meta(MetaType.URL, "https://video.twimg.com/ext_tw_video/560070131976392705/pu/pl/r1kgzh5PmLgium3-.m3u8", "application/x-mpegURL 0:30")));
assertEquals("video", t.getUserSubtitle());
}
@Test
public void itExpandsInstagramUrlsToMedia () throws Exception {
testPictureUrlExpansion("http://instagram.com/p/cT0bSXnMqi", false, "https://instagram.com/p/cT0bSXnMqi/media/?size=m");
testPictureUrlExpansion("http://instagram.com/p/cT0bSXnMqi/", false, "https://instagram.com/p/cT0bSXnMqi/media/?size=m");
testPictureUrlExpansion("https://www.instagram.com/p/BFdoIydtZzU/", false, "https://instagram.com/p/BFdoIydtZzU/media/?size=m");
}
@Test
public void itExpandsInstagramUrlsToMediaHd () throws Exception {
testPictureUrlExpansion("http://instagram.com/p/cT0bSXnMqi/", true, "https://instagram.com/p/cT0bSXnMqi/media/?size=l");
}
@Test
public void itExpandsTwitpicUrlsToMedia () throws Exception {
testPictureUrlExpansion("http://twitpic.com/d53yth", false, "https://twitpic.com/show/thumb/d53yth.jpg");
}
// TODO know that http://twitpic.com/photos/dalelane is a gallery (and has no thumb)
@Test
public void itExpandsImgurPageUrlsToMedia () throws Exception {
testPictureUrlExpansion("http://imgur.com/oxyFqMy", false, "https://i.imgur.com/oxyFqMyl.jpg");
}
@Test
public void itExpandsImgurPageUrlsToMediaHd () throws Exception {
testPictureUrlExpansion("http://imgur.com/oxyFqMy", true, "https://i.imgur.com/oxyFqMyh.jpg");
}
/**
* Needs an Imgur API call to map album to thumb. :(
*/
@Test
public void itExpandsImgurAlbumUrlsToNull () throws Exception {
testPictureUrlNonExpansion("http://imgur.com/a/8PKUl");
testPictureUrlNonExpansion("http://imgur.com/r/aww");
testPictureUrlNonExpansion("http://imgur.com/gallery/FpZwD");
}
@Test
public void itExpandsImgurAlbumEntryUrlsToMedia () throws Exception {
testPictureUrlExpansion("http://imgur.com/r/aww/qGSAGyf", false, "https://i.imgur.com/qGSAGyfl.jpg");
}
@Test
public void itConvertsImgurJpgUrlsToMedia () throws Exception {
testPictureUrlExpansion("http://i.imgur.com/dhadb0b.jpg", false, "https://i.imgur.com/dhadb0bl.jpg");
}
@Test
public void itConvertsImgurJpgUrlsToMediaHttps () throws Exception {
testPictureUrlExpansion("https://i.imgur.com/dhadb0b.jpg", false, "https://i.imgur.com/dhadb0bl.jpg");
}
@Test
public void itConvertsImgurPngUrlsToMedia () throws Exception {
testPictureUrlExpansion("http://i.imgur.com/SOLlJFo.png", false, "https://i.imgur.com/SOLlJFol.jpg");
}
@Test
public void itConvertsImgurGifUrlsToMedia () throws Exception {
testPictureUrlExpansion("http://i.imgur.com/AyLnEoz.gif", false, "https://i.imgur.com/AyLnEozl.jpg");
}
@Test
public void itConvertsImgurMultiToMediasButOnlyTheFirstFive () throws Exception {
testPictureUrlExpansion("https://imgur.com/TQcg7B7,okPllv3,zRRz0Zx,IpqDDiZ,GyYMeYy,WeyemzP,8cX3BY0,mXR6EgY,MY4uvJj,3CdRSrX,MkPEr0T", false,
"https://i.imgur.com/TQcg7B7l.jpg",
"https://i.imgur.com/okPllv3l.jpg",
"https://i.imgur.com/zRRz0Zxl.jpg",
"https://i.imgur.com/IpqDDiZl.jpg",
"https://i.imgur.com/GyYMeYyl.jpg");
}
@Test
public void itConvertsYfrogUrlsToMedia () throws Exception {
testPictureUrlExpansion("http://yfrog.com/oehccwlqj", false, "http://yfrog.com/oehccwlqj:small");
}
@Test
public void itConvertsYfrogUrlsToMediaHd () throws Exception {
testPictureUrlExpansion("http://yfrog.com/oehccwlqj", true, "http://yfrog.com/oehccwlqj:medium");
}
@Test
public void itConvertsTwippleUrlsToMedia () throws Exception {
testPictureUrlExpansion("http://p.twipple.jp/4pzli", false, "http://p.twipple.jp/show/large/4pzli");
}
@Test
public void itCanAddHdProfileImages () throws Exception {
final Status s = mockTweet("foo @twitter desu");
final Tweet t = TwitterUtils.convertTweet(this.account, s, 201, true);
assertEquals(s.getUser().getBiggerProfileImageURLHttps(), t.getAvatarUrl());
}
@Test
public void itExtractsMentionsButDoesNotIncludeMentionsOfSelf () throws Exception {
final Status s = mockTweet("foo @twitter desu");
final UserMentionEntity ume1 = mockUserMentionEntity("twitter", "Twitter", 100L);
final UserMentionEntity ume2 = mockUserMentionEntity("self", "Self", 200L);
when(s.getUserMentionEntities()).thenReturn(new UserMentionEntity[] { ume1, ume2 });
final Tweet t1 = TwitterUtils.convertTweet(this.account, s, 201, false);
assertThat(t1.getMetas(), hasItem(new Meta(MetaType.MENTION, "twitter", "Twitter")));
assertThat(t1.getMetas(), hasItem(new Meta(MetaType.MENTION, "self", "Self")));
final Tweet t2 = TwitterUtils.convertTweet(this.account, s, 200, false);
assertThat(t2.getMetas(), hasItem(new Meta(MetaType.MENTION, "twitter", "Twitter")));
assertThat(t2.getMetas(), not(hasItem(new Meta(MetaType.MENTION, "self", "Self"))));
}
@Test
public void itUsesOrigionalStatusForRetweets () throws Exception {
final Status s = mockTweet("a thing.", "them", "Them", 202);
final Status rt = mockTweet("RT @them: a thing.", "friend", "Friend", 201);
when(rt.isRetweet()).thenReturn(true);
when(rt.getRetweetedStatus()).thenReturn(s);
if (s.getCreatedAt().getTime() == rt.getCreatedAt().getTime()) throw new IllegalStateException("Bad mocking: created times are the same.");
final Tweet t = TwitterUtils.convertTweet(this.account, rt, 200, false);
assertEquals("a thing.", t.getBody());
assertEquals("them", t.getUsername());
assertEquals("via friend", t.getUserSubtitle());
assertEquals("Them", t.getFullname());
assertEquals("via Friend", t.getFullSubtitle());
assertEquals(s.getUser().getProfileImageURLHttps(), t.getAvatarUrl());
assertThat(t.getMetas(), hasItem(new Meta(MetaType.MENTION, "friend", "Friend")));
assertEquals(rt.getCreatedAt().getTime() / 1000L, t.getTime());
assertThat(t.getMetas(), hasItem(new Meta(MetaType.POST_TIME, String.valueOf(s.getCreatedAt().getTime() / 1000L))));
}
@Test
public void itDoesNotAddMentionForRetweetsByMe () throws Exception {
final Status s = mockTweet("a thing.", "them", "Them", 202);
final Status rt = mockTweet("RT @them: a thing.", "me", "Me", 200);
when(rt.isRetweet()).thenReturn(true);
when(rt.getRetweetedStatus()).thenReturn(s);
if (s.getCreatedAt().getTime() == rt.getCreatedAt().getTime()) throw new IllegalStateException("Bad mocking: created times are the same.");
final Tweet t = TwitterUtils.convertTweet(this.account, rt, 200, false);
assertEquals("a thing.", t.getBody());
assertEquals("them", t.getUsername());
assertEquals("via me", t.getUserSubtitle());
assertEquals("Them", t.getFullname());
assertEquals("via Me", t.getFullSubtitle());
assertEquals(s.getUser().getProfileImageURLHttps(), t.getAvatarUrl());
assertThat(t.getMetas(), not(hasItem(new Meta(MetaType.MENTION, "me", "Me"))));
assertEquals(rt.getCreatedAt().getTime() / 1000L, t.getTime());
assertThat(t.getMetas(), hasItem(new Meta(MetaType.POST_TIME, String.valueOf(s.getCreatedAt().getTime() / 1000L))));
}
@Test
public void itDoesNotDoubleMentionForRtAtMention () throws Exception {
final Status s = mockTweet("a thing @bob about a thing.", "them", "Them", 202);
final UserMentionEntity sUme = mockUserMentionEntity("bob", "Bob", 200L);
when(s.getUserMentionEntities()).thenReturn(new UserMentionEntity[] { sUme });
final Status rt = mockTweet("RT @them: a thing @bob about a thing.", "bob", "Bob", 200);
final UserMentionEntity rtUme = mockUserMentionEntity("bob", "Bob", 200L);
when(rt.getUserMentionEntities()).thenReturn(new UserMentionEntity[] { rtUme });
when(rt.isRetweet()).thenReturn(true);
when(rt.getRetweetedStatus()).thenReturn(s);
final Tweet t = TwitterUtils.convertTweet(this.account, rt, 100, false);
assertEquals("a thing @bob about a thing.", t.getBody());
assertThat(t.getMetas(), hasItem(new Meta(MetaType.MENTION, "bob", "Bob")));
final List<Meta> metasCopy = new ArrayList<Meta>(t.getMetas());
metasCopy.remove(new Meta(MetaType.MENTION, "bob", "Bob"));
assertThat(metasCopy, not(hasItem(new Meta(MetaType.MENTION, "bob", "Bob"))));
}
private void testPictureUrlExpansion (final String fromUrl, final boolean hdMedia, final String... toUrls) {
final Status s = mockTweetWithUrl(fromUrl);
final Tweet t = TwitterUtils.convertTweet(this.account, s, -1L, hdMedia);
for (final String toUrl : toUrls) {
assertThat(t.getMetas(), hasItem(new Meta(MetaType.MEDIA, toUrl, fromUrl)));
}
assertNoMetaOfType(t, MetaType.URL);
}
private void testPictureUrlNonExpansion (final String fromUrl) {
final Status s = mockTweetWithUrl(fromUrl);
final Tweet t = TwitterUtils.convertTweet(this.account, s, -1L, false);
for (final Meta meta : t.getMetas()) {
if (meta.getType() == MetaType.MEDIA) throw new AssertionError("Unexpected MEDIA in " + t.getMetas());
}
}
private static Status mockTweetWithUrl (final String url) {
final Status s = mockTweet("link: " + url);
final URLEntity ue = mock(URLEntity.class);
when(ue.getExpandedURL()).thenReturn(url);
when(ue.getURL()).thenReturn(url);
when(ue.getStart()).thenReturn(6);
when(ue.getEnd()).thenReturn(6 + url.length());
when(s.getURLEntities()).thenReturn(new URLEntity[] { ue });
return s;
}
private static Status mockTweetWithMedia (final String mediaPageUrl, final String mediaImgUrl) {
final Status s = mockTweet("media: " + mediaPageUrl);
final MediaEntity me = mockMediaEntry(mediaPageUrl, mediaImgUrl);
when(s.getMediaEntities()).thenReturn(new MediaEntity[] { me });
return s;
}
private static MediaEntity mockMediaEntry (final String mediaPageUrl, final String mediaImgUrl) {
final MediaEntity me = mock(MediaEntity.class);
when(me.getURL()).thenReturn(mediaPageUrl);
when(me.getExpandedURL()).thenReturn(mediaPageUrl);
when(me.getMediaURLHttps()).thenReturn(mediaImgUrl);
when(me.getStart()).thenReturn(7);
when(me.getEnd()).thenReturn(7 + mediaPageUrl.length());
return me;
}
private static Status mockTweet (final String msg) {
return mockTweet(msg, "screenname", "name", 1234);
}
private static long lastMockTime = System.currentTimeMillis();
private static Status mockTweet (final String msg, final String screenName, final String fullName, final long userId) {
final Status s = mock(Status.class);
when(s.getText()).thenReturn(msg);
final long t = System.currentTimeMillis();
lastMockTime = t > lastMockTime ? t : lastMockTime + 1;
when(s.getCreatedAt()).thenReturn(new Date(lastMockTime));
final User user = mock(User.class);
when(user.getScreenName()).thenReturn(screenName);
when(user.getName()).thenReturn(fullName);
when(user.getId()).thenReturn(userId);
when(user.getProfileImageURLHttps()).thenReturn("https://profile/" + screenName + "/image");
when(user.getBiggerProfileImageURLHttps()).thenReturn("https://profile/" + screenName + "/bigger_image");
when(s.getUser()).thenReturn(user);
return s;
}
private static UserMentionEntity mockUserMentionEntity (final String screenname, final String fullName, final long id) {
final UserMentionEntity ume = mock(UserMentionEntity.class);
when(ume.getScreenName()).thenReturn(screenname);
when(ume.getName()).thenReturn(fullName);
when(ume.getId()).thenReturn(id);
return ume;
}
private static void assertNoMetaOfType (final Tweet t, final MetaType type) throws AssertionError {
for (final Meta meta : t.getMetas()) {
if (meta.getType() == type) throw new AssertionError("Metas should not have any " + type + ": " + t.getMetas());
}
}
@Test
public void itMakesFriendlyErrorForHostNotFound () throws Exception {
final UnknownHostException uhe = new UnknownHostException("Unable to resolve host \"api.twitter.com\": No address associated with hostname");
final TwitterException te = new TwitterException("example", uhe);
assertEquals("Network error: Unable to resolve host \"api.twitter.com\": No address associated with hostname",
TwitterUtils.friendlyExceptionMessage(te));
}
@Test
public void itMakesFriendlyErrorForGenericIoException () throws Exception {
final IOException ioe = new IOException("OMG the network.");
final TwitterException te = new TwitterException("example", ioe);
assertEquals("Network error: java.io.IOException: OMG the network.", TwitterUtils.friendlyExceptionMessage(te));
}
@Test
public void itMakesFriendlyErrorForSslConnectionTimeout () throws Exception {
final SSLException se = new SSLException("Read error: ssl=0x5cbb0ce0: I/O error during system call, Connection timed out");
final TwitterException te = new TwitterException("example", se);
assertEquals("Network error: Connection timed out.", TwitterUtils.friendlyExceptionMessage(te));
}
@Test
public void itMakesFriendlyErrorForInternalJsonError () throws Exception {
final twitter4j.JSONException je = new twitter4j.JSONException("Expected a ',' or '}' at 7733 [character 7734 line 1]");
final TwitterException te = new TwitterException(je);
assertEquals("Network error: Invalid or incomplete data received.", TwitterUtils.friendlyExceptionMessage(te));
}
@Test
public void itMakesFriendlyErrorForTwitter64 () throws Exception {
assertEquals("Your account is suspended and is not permitted to access this feature. :(", TwitterUtils.friendlyExceptionMessage(makeTwitterEx(403, 64)));
}
@Test
public void itMakesFriendlyErrorForTwitter88 () throws Exception {
assertEquals("Rate limit exceeded. Please try again in a while.", TwitterUtils.friendlyExceptionMessage(makeTwitterEx(999, 88)));
}
@Test
public void itMakesFriendlyErrorForTwitter89 () throws Exception {
assertEquals("Invalid or expired token. Please try reauthenticating.", TwitterUtils.friendlyExceptionMessage(makeTwitterEx(999, 89)));
}
@Test
public void itMakesFriendlyErrorForTwitter130 () throws Exception {
assertEquals("OMG Twitter is over capacity!", TwitterUtils.friendlyExceptionMessage(makeTwitterEx(503, 130)));
}
@Test
public void itMakesFriendlyErrorForTwitter131 () throws Exception {
assertEquals("OMG Twitter is down!", TwitterUtils.friendlyExceptionMessage(makeTwitterEx(500, 131)));
}
@Test
public void itMakesFriendlyErrorForTwitter179 () throws Exception {
assertEquals("You are not authorized to see this status.", TwitterUtils.friendlyExceptionMessage(makeTwitterEx(403, 179)));
}
@Test
public void itMakesFriendlyErrorForTwitter185 () throws Exception {
assertEquals("You are over daily status update limit.", TwitterUtils.friendlyExceptionMessage(makeTwitterEx(403, 185)));
}
private static TwitterException makeTwitterEx (final int httpCode, final int twitterCode) {
final HttpResponse res = mock(HttpResponse.class);
when(res.getStatusCode()).thenReturn(httpCode);
final TwitterException te = new TwitterException("{\"errors\":[{\"message\":\"error\", \"code\": " + twitterCode + "}]}", res);
return te;
}
}