OSDN Git Service

Foursquareの新しい形式のチェックインURLのサムネイル表示に対応
[opentween/open-tween.git] / OpenTween.Tests / Thumbnail / Services / FoursquareCheckinTest.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2014 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
4 //
5 // This file is part of OpenTween.
6 //
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
10 // any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 // for more details.
16 //
17 // You should have received a copy of the GNU General Public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
21
22 using System;
23 using System.Collections.Generic;
24 using System.Linq;
25 using System.Net;
26 using System.Net.Http;
27 using System.Reflection;
28 using System.Runtime.InteropServices;
29 using System.Text;
30 using System.Threading;
31 using System.Threading.Tasks;
32 using System.Web;
33 using Moq;
34 using Xunit;
35 using Xunit.Extensions;
36
37 namespace OpenTween.Thumbnail.Services
38 {
39     public class FoursquareCheckinTest
40     {
41         [Fact]
42         public void UrlPattern_Test()
43         {
44             // 通常のチェックイン URL (www.swarmapp.com/c/***)
45             var match = FoursquareCheckin.UrlPatternRegex.Match("https://www.swarmapp.com/c/xxxxxxxx");
46             Assert.True(match.Success);
47             Assert.Equal("xxxxxxxx", match.Groups["checkin_id"].Value);
48         }
49
50         [Fact]
51         public void LegacyUrlPattern_Test()
52         {
53             // 古い形式の URL (foursquare.com/***/checkin/***?s=***)
54             var match = FoursquareCheckin.LegacyUrlPatternRegex.Match("https://foursquare.com/hogehoge/checkin/xxxxxxxx?s=aaaaaaa");
55             Assert.True(match.Success);
56             Assert.Equal("xxxxxxxx", match.Groups["checkin_id"].Value);
57             Assert.Equal("aaaaaaa", match.Groups["signature"].Value);
58
59             // 古い形式の URL (www.swarmapp.com/***/checkin/***?s=***)
60             match = FoursquareCheckin.LegacyUrlPatternRegex.Match("https://www.swarmapp.com/hogehoge/checkin/xxxxxxxx?s=aaaaaaa");
61             Assert.True(match.Success);
62             Assert.Equal("xxxxxxxx", match.Groups["checkin_id"].Value);
63             Assert.Equal("aaaaaaa", match.Groups["signature"].Value);
64         }
65
66         [Fact]
67         public async Task GetThumbnailInfoAsync_NewUrlTest()
68         {
69             var handler = new HttpMessageHandlerMock();
70             using (var http = new HttpClient(handler))
71             {
72                 var service = new FoursquareCheckin(http);
73
74                 handler.Enqueue(x =>
75                 {
76                     Assert.Equal(HttpMethod.Get, x.Method);
77                     Assert.Equal("https://api.foursquare.com/v2/checkins/resolve",
78                         x.RequestUri.GetLeftPart(UriPartial.Path));
79
80                     var query = HttpUtility.ParseQueryString(x.RequestUri.Query);
81
82                     Assert.Equal(ApplicationSettings.FoursquareClientId, query["client_id"]);
83                     Assert.Equal(ApplicationSettings.FoursquareClientSecret, query["client_secret"]);
84                     Assert.NotNull(query["v"]);
85                     Assert.Equal("xxxxxxxx", query["shortId"]);
86
87                     // リクエストに対するテストなのでレスポンスは適当に返す
88                     return new HttpResponseMessage(HttpStatusCode.NotFound);
89                 });
90
91                 var post = new PostClass
92                 {
93                     PostGeo = null,
94                 };
95
96                 var thumb = await service.GetThumbnailInfoAsync(
97                     "https://www.swarmapp.com/c/xxxxxxxx",
98                     post, CancellationToken.None);
99
100                 Assert.Equal(0, handler.QueueCount);
101             }
102         }
103
104         [Fact]
105         public async Task GetThumbnailInfoAsync_LegacyUrlTest()
106         {
107             var handler = new HttpMessageHandlerMock();
108             using (var http = new HttpClient(handler))
109             {
110                 var service = new FoursquareCheckin(http);
111
112                 handler.Enqueue(x =>
113                 {
114                     Assert.Equal(HttpMethod.Get, x.Method);
115                     Assert.Equal("https://api.foursquare.com/v2/checkins/xxxxxxxx",
116                         x.RequestUri.GetLeftPart(UriPartial.Path));
117
118                     var query = HttpUtility.ParseQueryString(x.RequestUri.Query);
119
120                     Assert.Equal(ApplicationSettings.FoursquareClientId, query["client_id"]);
121                     Assert.Equal(ApplicationSettings.FoursquareClientSecret, query["client_secret"]);
122                     Assert.NotNull(query["v"]);
123                     Assert.Null(query["signature"]);
124
125                     // リクエストに対するテストなのでレスポンスは適当に返す
126                     return new HttpResponseMessage(HttpStatusCode.NotFound);
127                 });
128
129                 var post = new PostClass
130                 {
131                     PostGeo = null,
132                 };
133
134                 var thumb = await service.GetThumbnailInfoAsync(
135                     "https://foursquare.com/hogehoge/checkin/xxxxxxxx",
136                     post, CancellationToken.None);
137
138                 Assert.Equal(0, handler.QueueCount);
139             }
140         }
141
142         [Fact]
143         public async Task GetThumbnailInfoAsync_LegacyUrlWithSignatureTest()
144         {
145             var handler = new HttpMessageHandlerMock();
146             using (var http = new HttpClient(handler))
147             {
148                 var service = new FoursquareCheckin(http);
149
150                 handler.Enqueue(x =>
151                 {
152                     Assert.Equal(HttpMethod.Get, x.Method);
153                     Assert.Equal("https://api.foursquare.com/v2/checkins/xxxxxxxx",
154                         x.RequestUri.GetLeftPart(UriPartial.Path));
155
156                     var query = HttpUtility.ParseQueryString(x.RequestUri.Query);
157
158                     Assert.Equal(ApplicationSettings.FoursquareClientId, query["client_id"]);
159                     Assert.Equal(ApplicationSettings.FoursquareClientSecret, query["client_secret"]);
160                     Assert.NotNull(query["v"]);
161                     Assert.Equal("aaaaaaa", query["signature"]);
162
163                     // リクエストに対するテストなのでレスポンスは適当に返す
164                     return new HttpResponseMessage(HttpStatusCode.NotFound);
165                 });
166
167                 var post = new PostClass
168                 {
169                     PostGeo = null,
170                 };
171
172                 var thumb = await service.GetThumbnailInfoAsync(
173                     "https://foursquare.com/hogehoge/checkin/xxxxxxxx?s=aaaaaaa",
174                     post, CancellationToken.None);
175
176                 Assert.Equal(0, handler.QueueCount);
177             }
178         }
179
180         [Fact]
181         public async Task GetThumbnailInfoAsync_GeoLocatedTweetTest()
182         {
183             var handler = new HttpMessageHandlerMock();
184             using (var http = new HttpClient(handler))
185             {
186                 var service = new FoursquareCheckin(http);
187
188                 handler.Enqueue(x =>
189                 {
190                     // このリクエストは実行されないはず
191                     Assert.True(false);
192                     return new HttpResponseMessage(HttpStatusCode.NotFound);
193                 });
194
195                 // 既にジオタグが付いているツイートに対しては何もしない
196                 var post = new PostClass
197                 {
198                     PostGeo = new PostClass.StatusGeo(134.04693603515625, 34.35067978344854),
199                 };
200
201                 var thumb = await service.GetThumbnailInfoAsync(
202                     "https://www.swarmapp.com/c/xxxxxxxx",
203                     post, CancellationToken.None);
204
205                 Assert.Equal(1, handler.QueueCount);
206             }
207         }
208
209         [Fact]
210         public void ParseInLocation_Test()
211         {
212             var json = @"{
213   ""meta"": { ""code"": 200 },
214   ""response"": {
215     ""checkin"": {
216       ""id"": ""xxxxxxxxx"",
217       ""type"": ""checkin"",
218       ""venue"": {
219         ""id"": ""4b73dedcf964a5206bbe2de3"",
220         ""name"": ""高松駅 (Takamatsu Sta.)"",
221         ""location"": {
222           ""lat"": 34.35067978344854,
223           ""lng"": 134.04693603515625
224         }
225       }
226     }
227   }
228 }";
229             var jsonBytes = Encoding.UTF8.GetBytes(json);
230             var location = FoursquareCheckin.ParseIntoLocation(jsonBytes);
231
232             Assert.NotNull(location);
233             Assert.Equal(34.35067978344854, location.Latitude);
234             Assert.Equal(134.04693603515625, location.Longitude);
235         }
236
237         [Fact]
238         public void ParseInLocation_PlanetTest()
239         {
240             var json = @"{
241   ""meta"": { ""code"": 200 },
242   ""response"": {
243     ""checkin"": {
244       ""id"": ""xxxxxxxxx"",
245       ""type"": ""checkin"",
246       ""venue"": {
247         ""id"": ""5069d8bdc640385aa7711fe4"",
248         ""name"": ""Gale Crater"",
249         ""location"": {
250           ""planet"": ""mars"",
251           ""lat"": 34.201694,
252           ""lng"": -118.17166
253         }
254       }
255     }
256   }
257 }";
258             var jsonBytes = Encoding.UTF8.GetBytes(json);
259             var location = FoursquareCheckin.ParseIntoLocation(jsonBytes);
260
261             // 地球以外の位置にあるベニューに対しては null を返す
262             Assert.Null(location);
263         }
264
265         [Fact]
266         public void ParseInLocation_VenueNullTest()
267         {
268             var json = @"{
269   ""meta"": { ""code"": 200 },
270   ""response"": {
271     ""checkin"": {
272       ""id"": ""xxxxxxxxx"",
273       ""type"": ""checkin"",
274       ""venue"": null
275     }
276   }
277 }";
278             var jsonBytes = Encoding.UTF8.GetBytes(json);
279             var location = FoursquareCheckin.ParseIntoLocation(jsonBytes);
280
281             // ベニュー情報が得られなかった場合は null を返す
282             Assert.Null(location);
283         }
284     }
285 }