OSDN Git Service

UserByScreenNameで空のユーザー情報が返ってきた場合にエラーとして扱う
[opentween/open-tween.git] / OpenTween.Tests / MediaSelectorTest.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2014 spx (@5px)
3 // Copyright (c) 2023 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
4 // All rights reserved.
5 //
6 // This file is part of OpenTween.
7 //
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 3 of the License, or (at your option)
11 // any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 // for more details.
17 //
18 // You should have received a copy of the GNU General Public License along
19 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
20 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
21 // Boston, MA 02110-1301, USA.
22
23 using System;
24 using System.Collections.Generic;
25 using System.Drawing;
26 using System.IO;
27 using System.Linq;
28 using System.Reflection;
29 using System.Runtime.InteropServices;
30 using System.Text;
31 using Moq;
32 using OpenTween.Api;
33 using OpenTween.Api.DataModel;
34 using Xunit;
35
36 namespace OpenTween
37 {
38     public class MediaSelectorTest
39     {
40         public MediaSelectorTest()
41             => this.MyCommonSetup();
42
43         private void MyCommonSetup()
44         {
45             var mockAssembly = new Mock<_Assembly>();
46             mockAssembly.Setup(m => m.GetName()).Returns(new AssemblyName("OpenTween"));
47
48             MyCommon.EntryAssembly = mockAssembly.Object;
49         }
50
51         [Fact]
52         public void SelectedMediaServiceIndex_Test()
53         {
54             using var twitterApi = new TwitterApi();
55             using var twitter = new Twitter(twitterApi);
56             using var mediaSelector = new MediaSelector();
57             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
58
59             Assert.Equal("Twitter", mediaSelector.MediaServices[0].Key);
60             Assert.Equal("Imgur", mediaSelector.MediaServices[1].Key);
61
62             mediaSelector.SelectedMediaServiceName = "Imgur";
63             Assert.Equal(1, mediaSelector.SelectedMediaServiceIndex);
64
65             mediaSelector.SelectedMediaServiceName = "Twitter";
66             Assert.Equal(0, mediaSelector.SelectedMediaServiceIndex);
67         }
68
69         [Fact]
70         public void SelectMediaService_TwitterTest()
71         {
72             using var twitterApi = new TwitterApi();
73             using var twitter = new Twitter(twitterApi);
74             using var mediaSelector = new MediaSelector();
75             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
76             mediaSelector.SelectMediaService("Twitter");
77
78             Assert.Contains(mediaSelector.MediaServices, x => x.Key == "Twitter");
79
80             // 投稿先に Twitter が選択されている
81             Assert.Equal("Twitter", mediaSelector.SelectedMediaServiceName);
82
83             // 代替テキストが入力可能な状態
84             Assert.True(mediaSelector.CanUseAltText);
85         }
86
87         [Fact]
88         public void SelectMediaService_ImgurTest()
89         {
90             using var twitterApi = new TwitterApi();
91             using var twitter = new Twitter(twitterApi);
92             using var mediaSelector = new MediaSelector();
93             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
94             mediaSelector.SelectMediaService("Imgur");
95
96             // 投稿先に Imgur が選択されている
97             Assert.Equal("Imgur", mediaSelector.SelectedMediaServiceName);
98
99             // 代替テキストが入力できない状態
100             Assert.False(mediaSelector.CanUseAltText);
101         }
102
103         [Fact]
104         public void AddMediaItem_FilePath_SingleTest()
105         {
106             using var twitterApi = new TwitterApi();
107             using var twitter = new Twitter(twitterApi);
108             using var mediaSelector = new MediaSelector();
109             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
110             mediaSelector.SelectMediaService("Twitter");
111
112             var images = new[] { "Resources/re.gif" };
113             mediaSelector.AddMediaItemFromFilePath(images);
114
115             // 画像が 1 つ追加された状態
116             Assert.Single(mediaSelector.MediaItems);
117
118             // 1 枚目の画像が表示されている
119             Assert.Equal(0, mediaSelector.SelectedMediaItemIndex);
120             Assert.Equal(Path.GetFullPath("Resources/re.gif"), mediaSelector.SelectedMediaItem!.Path);
121
122             using var imageStream = File.OpenRead("Resources/re.gif");
123             using var expectedImage = MemoryImage.CopyFromStream(imageStream);
124             using var actualImage = mediaSelector.SelectedMediaItem.CreateImage();
125             Assert.Equal(expectedImage, actualImage);
126         }
127
128         [Fact]
129         public void AddMediaItem_MemoryImageTest()
130         {
131             using var twitterApi = new TwitterApi();
132             using var twitter = new Twitter(twitterApi);
133             using var mediaSelector = new MediaSelector();
134             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
135             mediaSelector.SelectMediaService("Twitter");
136
137             using (var bitmap = new Bitmap(width: 200, height: 200))
138                 mediaSelector.AddMediaItemFromImage(bitmap);
139
140             // 画像が 1 つ追加された状態
141             Assert.Single(mediaSelector.MediaItems);
142
143             // 1 枚目の画像が表示されている
144             Assert.Equal(0, mediaSelector.SelectedMediaItemIndex);
145             Assert.Matches(@"^<>MemoryImage://\d+.png$", mediaSelector.SelectedMediaItem!.Path);
146
147             using (var bitmap = new Bitmap(width: 200, height: 200))
148             {
149                 using var expectedImage = MemoryImage.CopyFromImage(bitmap);
150                 using var actualImage = mediaSelector.SelectedMediaItem.CreateImage();
151                 Assert.Equal(expectedImage, actualImage);
152             }
153         }
154
155         [Fact]
156         public void AddMediaItem_FilePath_MultipleTest()
157         {
158             using var twitterApi = new TwitterApi();
159             using var twitter = new Twitter(twitterApi);
160             using var mediaSelector = new MediaSelector();
161             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
162             mediaSelector.SelectMediaService("Twitter");
163
164             var images = new[] { "Resources/re.gif", "Resources/re1.png" };
165             mediaSelector.AddMediaItemFromFilePath(images);
166
167             // 画像が 2 つ追加された状態
168             Assert.Equal(2, mediaSelector.MediaItems.Count);
169
170             // 最後の画像(2 枚目)が表示されている
171             Assert.Equal(1, mediaSelector.SelectedMediaItemIndex);
172             Assert.Equal(Path.GetFullPath("Resources/re1.png"), mediaSelector.SelectedMediaItem!.Path);
173
174             using var imageStream = File.OpenRead("Resources/re1.png");
175             using var expectedImage = MemoryImage.CopyFromStream(imageStream);
176             using var actualImage = mediaSelector.SelectedMediaItem.CreateImage();
177             Assert.Equal(expectedImage, actualImage);
178         }
179
180         [Fact]
181         public void ClearMediaItems_Test()
182         {
183             using var twitterApi = new TwitterApi();
184             using var twitter = new Twitter(twitterApi);
185             using var mediaSelector = new MediaSelector();
186             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
187             mediaSelector.SelectMediaService("Twitter");
188
189             mediaSelector.AddMediaItemFromFilePath(new[] { "Resources/re.gif" });
190
191             var mediaItems = mediaSelector.MediaItems.ToArray();
192             var thumbnailImages = mediaSelector.ThumbnailList.ToArray(); // 表示中の画像
193
194             mediaSelector.ClearMediaItems();
195
196             Assert.True(mediaItems.All(x => x.IsDisposed));
197             Assert.True(thumbnailImages.All(x => x.IsDisposed));
198         }
199
200         [Fact]
201         public void DetachMediaItems_Test()
202         {
203             using var twitterApi = new TwitterApi();
204             using var twitter = new Twitter(twitterApi);
205             using var mediaSelector = new MediaSelector();
206             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
207             mediaSelector.SelectMediaService("Twitter");
208
209             mediaSelector.AddMediaItemFromFilePath(new[] { "Resources/re.gif" });
210
211             var thumbnailImages = mediaSelector.ThumbnailList.ToArray();
212
213             var detachedMediaItems = mediaSelector.DetachMediaItems();
214
215             Assert.Empty(mediaSelector.MediaItems);
216             Assert.True(thumbnailImages.All(x => x.IsDisposed));
217
218             // DetachMediaItems で切り離された MediaItem は破棄しない
219             Assert.True(detachedMediaItems.All(x => !x.IsDisposed));
220         }
221
222         [Fact]
223         public void SelectedMediaItemChange_Test()
224         {
225             using var twitterApi = new TwitterApi();
226             using var twitter = new Twitter(twitterApi);
227             using var mediaSelector = new MediaSelector();
228             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
229             mediaSelector.SelectMediaService("Twitter");
230
231             var images = new[] { "Resources/re.gif", "Resources/re1.png" };
232             mediaSelector.AddMediaItemFromFilePath(images);
233
234             mediaSelector.SelectedMediaItemIndex = 0;
235
236             // 1 ページ目
237             Assert.Equal(Path.GetFullPath("Resources/re.gif"), mediaSelector.SelectedMediaItem!.Path);
238
239             using (var imageStream = File.OpenRead("Resources/re.gif"))
240             {
241                 using var expectedImage = MemoryImage.CopyFromStream(imageStream);
242                 using var actualImage = mediaSelector.SelectedMediaItem.CreateImage();
243                 Assert.Equal(expectedImage, actualImage);
244             }
245
246             mediaSelector.SelectedMediaItemIndex = 1;
247
248             // 2 ページ目
249             Assert.Equal(Path.GetFullPath("Resources/re1.png"), mediaSelector.SelectedMediaItem!.Path);
250
251             using (var imageStream = File.OpenRead("Resources/re1.png"))
252             {
253                 using var expectedImage = MemoryImage.CopyFromStream(imageStream);
254                 using var actualImage = mediaSelector.SelectedMediaItem.CreateImage();
255                 Assert.Equal(expectedImage, actualImage);
256             }
257         }
258
259         [Fact]
260         public void SelectedMediaItemChange_DisposeTest()
261         {
262             using var twitterApi = new TwitterApi();
263             using var twitter = new Twitter(twitterApi);
264             using var mediaSelector = new MediaSelector();
265             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
266             mediaSelector.SelectMediaService("Twitter");
267
268             var images = new[] { "Resources/re.gif", "Resources/re1.png" };
269             mediaSelector.AddMediaItemFromFilePath(images);
270
271             // 1 枚目
272             mediaSelector.SelectedMediaItemIndex = 0;
273             var firstImage = mediaSelector.SelectedMediaItemImage;
274
275             // 2 枚目
276             mediaSelector.SelectedMediaItemIndex = 1;
277             var secondImage = mediaSelector.SelectedMediaItemImage;
278
279             Assert.True(firstImage!.IsDisposed);
280         }
281
282         [Fact]
283         public void SetSelectedMediaAltText_Test()
284         {
285             using var twitterApi = new TwitterApi();
286             using var twitter = new Twitter(twitterApi);
287             using var mediaSelector = new MediaSelector();
288             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
289             mediaSelector.SelectMediaService("Twitter");
290
291             var images = new[] { "Resources/re.gif", "Resources/re1.png" };
292             mediaSelector.AddMediaItemFromFilePath(images);
293
294             // 1 ページ目
295             mediaSelector.SelectedMediaItemIndex = 0;
296             mediaSelector.SetSelectedMediaAltText("Page 1");
297
298             // 2 ページ目
299             mediaSelector.SelectedMediaItemIndex = 1;
300             mediaSelector.SetSelectedMediaAltText("Page 2");
301
302             Assert.Equal("Page 1", mediaSelector.MediaItems[0].AltText);
303             Assert.Equal("Page 2", mediaSelector.MediaItems[1].AltText);
304         }
305
306         [Fact]
307         public void Validate_PassTest()
308         {
309             using var twitterApi = new TwitterApi();
310             using var twitter = new Twitter(twitterApi);
311             using var mediaSelector = new MediaSelector();
312             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
313             mediaSelector.SelectMediaService("Twitter");
314
315             using var mediaItem = TestUtils.CreateDummyMediaItem();
316             mediaSelector.AddMediaItem(mediaItem);
317             Assert.Equal(MediaSelectorErrorType.None, mediaSelector.Validate(out var rejected));
318             Assert.Null(rejected);
319         }
320
321         [Fact]
322         public void Validate_EmptyErrorTest()
323         {
324             using var twitterApi = new TwitterApi();
325             using var twitter = new Twitter(twitterApi);
326             using var mediaSelector = new MediaSelector();
327             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
328             mediaSelector.SelectMediaService("Twitter");
329
330             Assert.Equal(
331                 MediaSelectorErrorType.MediaItemNotSet,
332                 mediaSelector.Validate(out var rejected)
333             );
334             Assert.Null(rejected);
335         }
336
337         [Fact]
338         public void Validate_ServiceNotSelectedErrorTest()
339         {
340             using var twitterApi = new TwitterApi();
341             using var twitter = new Twitter(twitterApi);
342             using var mediaSelector = new MediaSelector();
343             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
344
345             using var mediaItem = TestUtils.CreateDummyMediaItem();
346             mediaSelector.AddMediaItem(mediaItem);
347             Assert.Equal(
348                 MediaSelectorErrorType.ServiceNotSelected,
349                 mediaSelector.Validate(out var rejected)
350             );
351             Assert.Null(rejected);
352         }
353
354         [Fact]
355         public void Validate_ExtensionErrorTest()
356         {
357             using var twitterApi = new TwitterApi();
358             using var twitter = new Twitter(twitterApi);
359             using var mediaSelector = new MediaSelector();
360             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
361             mediaSelector.SelectMediaService("Twitter");
362
363             var mock = new Mock<IMediaItem>();
364             mock.Setup(x => x.CreateImage()).Returns(() => TestUtils.CreateDummyImage());
365             mock.Setup(x => x.Extension).Returns(".exe");
366             mock.Setup(x => x.Size).Returns(1_000_000);
367
368             mediaSelector.AddMediaItem(mock.Object);
369             Assert.Equal(
370                 MediaSelectorErrorType.UnsupportedFileExtension,
371                 mediaSelector.Validate(out var rejected)
372             );
373             Assert.Same(mock.Object, rejected);
374         }
375
376         [Fact]
377         public void Validate_FileSizeErrorTest()
378         {
379             using var twitterApi = new TwitterApi();
380             using var twitter = new Twitter(twitterApi);
381             using var mediaSelector = new MediaSelector();
382             mediaSelector.InitializeServices(twitter, TwitterConfiguration.DefaultConfiguration());
383             mediaSelector.SelectMediaService("Twitter");
384
385             var mock = new Mock<IMediaItem>();
386             mock.Setup(x => x.CreateImage()).Returns(() => TestUtils.CreateDummyImage());
387             mock.Setup(x => x.Extension).Returns(".png");
388             mock.Setup(x => x.Size).Returns(1_000_000_000); // 1GB
389
390             mediaSelector.AddMediaItem(mock.Object);
391             Assert.Equal(
392                 MediaSelectorErrorType.FileSizeExceeded,
393                 mediaSelector.Validate(out var rejected)
394             );
395             Assert.Same(mock.Object, rejected);
396         }
397
398         [Fact]
399         public void MoveSelectedMediaItemToPrevious_Test()
400         {
401             using var twitterApi = new TwitterApi();
402             using var twitter = new Twitter(twitterApi);
403             using var mediaSelector = new MediaSelector();
404
405             mediaSelector.AddMediaItemFromFilePath(new[] { "Resources/re.gif", "Resources/re1.png" });
406             mediaSelector.SelectedMediaItemIndex = 1;
407             mediaSelector.MoveSelectedMediaItemToPrevious();
408
409             Assert.Equal("re1.png", mediaSelector.MediaItems[0].Name);
410             Assert.Equal("re.gif", mediaSelector.MediaItems[1].Name);
411             Assert.Equal(0, mediaSelector.SelectedMediaItemIndex);
412         }
413
414         [Fact]
415         public void MoveSelectedMediaItemToNext_Test()
416         {
417             using var twitterApi = new TwitterApi();
418             using var twitter = new Twitter(twitterApi);
419             using var mediaSelector = new MediaSelector();
420
421             mediaSelector.AddMediaItemFromFilePath(new[] { "Resources/re.gif", "Resources/re1.png" });
422             mediaSelector.SelectedMediaItemIndex = 0;
423             mediaSelector.MoveSelectedMediaItemToNext();
424
425             Assert.Equal("re1.png", mediaSelector.MediaItems[0].Name);
426             Assert.Equal("re.gif", mediaSelector.MediaItems[1].Name);
427             Assert.Equal(1, mediaSelector.SelectedMediaItemIndex);
428         }
429
430         [Fact]
431         public void RemoveSelectedMediaItem_Test()
432         {
433             using var twitterApi = new TwitterApi();
434             using var twitter = new Twitter(twitterApi);
435             using var mediaSelector = new MediaSelector();
436
437             mediaSelector.AddMediaItemFromFilePath(new[] { "Resources/re.gif", "Resources/re1.png" });
438             mediaSelector.SelectedMediaItemIndex = 0;
439             mediaSelector.RemoveSelectedMediaItem();
440
441             Assert.Single(mediaSelector.MediaItems);
442             Assert.Equal("re1.png", mediaSelector.MediaItems[0].Name);
443             Assert.Equal(-1, mediaSelector.SelectedMediaItemIndex);
444         }
445     }
446 }