1 // OpenTween - Client of Twitter
2 // Copyright (c) 2014 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
5 // This file is part of OpenTween.
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)
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
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.
23 using System.Collections.Generic;
25 using System.Reflection;
28 using Xunit.Extensions;
30 namespace OpenTween.Models
32 public class TabInformationTest
34 private TabInformations tabinfo;
36 public TabInformationTest()
38 this.tabinfo = Activator.CreateInstance(typeof(TabInformations), true) as TabInformations;
40 // TabInformation.GetInstance() で取得できるようにする
41 var field = typeof(TabInformations).GetField("_instance",
42 BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.SetField);
43 field.SetValue(null, this.tabinfo);
46 this.tabinfo.AddTab(new HomeTabModel("Recent"));
47 this.tabinfo.AddTab(new MentionsTabModel("Reply"));
48 this.tabinfo.AddTab(new DirectMessagesTabModel("DM"));
49 this.tabinfo.AddTab(new FavoritesTabModel("Favorites"));
53 public void AddTab_Test()
55 var tab = new FilterTabModel("MyTab");
56 var ret = this.tabinfo.AddTab(tab);
59 Assert.Same(tab, this.tabinfo.Tabs.Values.Last());
63 public void AddTab_DuplicateTest()
65 var ret = this.tabinfo.AddTab(new FilterTabModel("Recent"));
71 public void MakeTabName_Test()
73 var baseTabName = "NewTab";
74 Assert.Equal("NewTab", this.tabinfo.MakeTabName(baseTabName, 5));
78 public void MakeTabName_RetryTest()
80 this.tabinfo.AddTab(new FilterTabModel("NewTab"));
81 this.tabinfo.AddTab(new FilterTabModel("NewTab2"));
83 var baseTabName = "NewTab";
84 Assert.Equal("NewTab3", this.tabinfo.MakeTabName(baseTabName, 5));
88 public void MakeTabName_RetryErrorTest()
90 this.tabinfo.AddTab(new FilterTabModel("NewTab"));
91 this.tabinfo.AddTab(new FilterTabModel("NewTab2"));
92 this.tabinfo.AddTab(new FilterTabModel("NewTab3"));
93 this.tabinfo.AddTab(new FilterTabModel("NewTab4"));
94 this.tabinfo.AddTab(new FilterTabModel("NewTab5"));
96 var baseTabName = "NewTab";
97 Assert.Throws<TabException>(() => this.tabinfo.MakeTabName(baseTabName, 5));
101 public void IsMuted_Test()
103 this.tabinfo.MuteUserIds = new HashSet<long> { 12345L };
105 var post = new PostClass
110 Assert.True(this.tabinfo.IsMuted(post, isHomeTimeline: true));
114 public void IsMuted_NotMutingTest()
116 this.tabinfo.MuteUserIds = new HashSet<long> { 12345L };
118 var post = new PostClass
123 Assert.False(this.tabinfo.IsMuted(post, isHomeTimeline: true));
127 public void IsMuted_RetweetTest()
129 this.tabinfo.MuteUserIds = new HashSet<long> { 12345L };
131 var post = new PostClass
134 RetweetedByUserId = 12345L,
137 Assert.True(this.tabinfo.IsMuted(post, isHomeTimeline: true));
141 public void IsMuted_RetweetNotMutingTest()
143 this.tabinfo.MuteUserIds = new HashSet<long> { 12345L };
145 var post = new PostClass
148 RetweetedByUserId = 22222L,
151 Assert.False(this.tabinfo.IsMuted(post, isHomeTimeline: true));
155 public void IsMuted_ReplyTest()
157 this.tabinfo.MuteUserIds = new HashSet<long> { 12345L };
159 // ミュート対象のユーザーであってもリプライの場合は対象外とする
160 var post = new PostClass
163 Text = "@foo hogehoge",
166 Assert.False(this.tabinfo.IsMuted(post, isHomeTimeline: true));
170 public void IsMuted_NotInHomeTimelineTest()
172 this.tabinfo.MuteUserIds = new HashSet<long> { 12345L };
174 // Recent以外のタブ(検索など)の場合は対象外とする
175 var post = new PostClass
180 Assert.False(this.tabinfo.IsMuted(post, isHomeTimeline: false));
184 public void IsMuted_MuteTabRulesTest()
186 this.tabinfo.MuteUserIds = new HashSet<long> { };
188 var muteTab = new MuteTabModel();
189 muteTab.AddFilter(new PostFilterRule
194 this.tabinfo.AddTab(muteTab);
196 var post = new PostClass
202 Assert.True(this.tabinfo.IsMuted(post, isHomeTimeline: true));
206 public void IsMuted_MuteTabRules_NotInHomeTimelineTest()
208 this.tabinfo.MuteUserIds = new HashSet<long> { };
210 var muteTab = new MuteTabModel();
211 muteTab.AddFilter(new PostFilterRule
216 this.tabinfo.AddTab(muteTab);
218 // ミュートタブによるミュートはリプライも対象とする
219 var post = new PostClass
223 Text = "@hoge hogehoge",
226 Assert.True(this.tabinfo.IsMuted(post, isHomeTimeline: false));
230 public void SetReadAllTab_MarkAsReadTest()
232 var tab1 = new PublicSearchTabModel("search1");
233 var tab2 = new PublicSearchTabModel("search2");
235 this.tabinfo.AddTab(tab1);
236 this.tabinfo.AddTab(tab2);
238 // search1 に追加するツイート (StatusId: 100, 150, 200; すべて未読)
239 tab1.UnreadManage = true;
240 tab1.AddPostQueue(new PostClass { StatusId = 100L, IsRead = false });
241 tab1.AddPostQueue(new PostClass { StatusId = 150L, IsRead = false });
242 tab1.AddPostQueue(new PostClass { StatusId = 200L, IsRead = false });
244 // search2 に追加するツイート (StatusId: 150, 200, 250; すべて未読)
245 tab2.UnreadManage = true;
246 tab2.AddPostQueue(new PostClass { StatusId = 150L, IsRead = false });
247 tab2.AddPostQueue(new PostClass { StatusId = 200L, IsRead = false });
248 tab2.AddPostQueue(new PostClass { StatusId = 250L, IsRead = false });
250 this.tabinfo.DistributePosts();
251 this.tabinfo.SubmitUpdate();
254 Assert.Equal(3, tab1.UnreadCount);
255 Assert.Equal(3, tab2.UnreadCount);
259 // StatusId: 200 を既読にする (search1, search2 両方に含まれる)
260 this.tabinfo.SetReadAllTab(200L, read: true);
261 Assert.Equal(2, tab1.UnreadCount);
262 Assert.Equal(2, tab2.UnreadCount);
264 // StatusId: 100 を既読にする (search1 のみに含まれる)
265 this.tabinfo.SetReadAllTab(100L, read: true);
266 Assert.Equal(1, tab1.UnreadCount);
267 Assert.Equal(2, tab2.UnreadCount);
271 public void SetReadAllTab_MarkAsUnreadTest()
273 var tab1 = new PublicSearchTabModel("search1");
274 var tab2 = new PublicSearchTabModel("search2");
276 this.tabinfo.AddTab(tab1);
277 this.tabinfo.AddTab(tab2);
279 // search1 に追加するツイート (StatusId: 100, 150, 200; すべて既読)
280 tab1.UnreadManage = true;
281 tab1.AddPostQueue(new PostClass { StatusId = 100L, IsRead = true });
282 tab1.AddPostQueue(new PostClass { StatusId = 150L, IsRead = true });
283 tab1.AddPostQueue(new PostClass { StatusId = 200L, IsRead = true });
285 // search2 に追加するツイート (StatusId: 150, 200, 250; すべて既読)
286 tab2.UnreadManage = true;
287 tab2.AddPostQueue(new PostClass { StatusId = 150L, IsRead = true });
288 tab2.AddPostQueue(new PostClass { StatusId = 200L, IsRead = true });
289 tab2.AddPostQueue(new PostClass { StatusId = 250L, IsRead = true });
291 this.tabinfo.DistributePosts();
292 this.tabinfo.SubmitUpdate();
295 Assert.Equal(0, tab1.UnreadCount);
296 Assert.Equal(0, tab2.UnreadCount);
300 // StatusId: 200 を未読にする (search1, search2 両方に含まれる)
301 this.tabinfo.SetReadAllTab(200L, read: false);
302 Assert.Equal(1, tab1.UnreadCount);
303 Assert.Equal(1, tab2.UnreadCount);
305 // StatusId: 100 を未読にする (search1 のみに含まれる)
306 this.tabinfo.SetReadAllTab(100L, read: false);
307 Assert.Equal(2, tab1.UnreadCount);
308 Assert.Equal(1, tab2.UnreadCount);
312 public void SetReadHomeTab_Test()
314 var homeTab = this.tabinfo.Tabs["Recent"];
316 // Recent に追加するツイート (StatusId: 100, 150, 200; すべて未読)
317 homeTab.UnreadManage = true;
318 this.tabinfo.AddPost(new PostClass { StatusId = 100L, IsRead = false });
319 this.tabinfo.AddPost(new PostClass { StatusId = 150L, IsRead = false });
320 this.tabinfo.AddPost(new PostClass { StatusId = 200L, IsRead = false });
322 this.tabinfo.DistributePosts();
323 this.tabinfo.SubmitUpdate();
326 Assert.Equal(3, homeTab.UnreadCount);
328 // Recent タブのツイートをすべて未読にする
329 this.tabinfo.SetReadHomeTab();
330 Assert.Equal(0, homeTab.UnreadCount);
334 public void SetReadHomeTab_ContainsReplyTest()
336 var homeTab = this.tabinfo.Tabs["Recent"];
338 // Recent に追加するツイート (StatusId: 100, 150, 200; すべて未読)
339 // StatusId: 150 は未読だがリプライ属性が付いている
340 homeTab.UnreadManage = true;
341 this.tabinfo.AddPost(new PostClass { StatusId = 100L, IsRead = false });
342 this.tabinfo.AddPost(new PostClass { StatusId = 150L, IsRead = false, IsReply = true });
343 this.tabinfo.AddPost(new PostClass { StatusId = 200L, IsRead = false });
345 this.tabinfo.DistributePosts();
346 this.tabinfo.SubmitUpdate();
349 Assert.Equal(3, homeTab.UnreadCount);
351 // Recent タブのツイートをすべて未読にする
352 this.tabinfo.SetReadHomeTab();
354 // リプライである StatusId: 150 を除いてすべて未読になっている
355 Assert.Equal(1, homeTab.UnreadCount);
356 Assert.Equal(150L, homeTab.NextUnreadId);
360 public void SetReadHomeTab_ContainsFilterHitTest()
362 var homeTab = this.tabinfo.Tabs["Recent"];
364 // Recent に追加するツイート (StatusId: 100, 150, 200; すべて未読)
365 homeTab.UnreadManage = true;
366 this.tabinfo.AddPost(new PostClass { StatusId = 100L, IsRead = false });
367 this.tabinfo.AddPost(new PostClass { StatusId = 150L, IsRead = false });
368 this.tabinfo.AddPost(new PostClass { StatusId = 200L, IsRead = false });
370 // StatusId: 150 だけ FilterTab の振り分けルールにヒットする (PostClass.FilterHit が true になる)
371 var filterTab = new FilterTabModel("FilterTab");
372 filterTab.AddFilter(TestPostFilterRule.Create(x =>
373 x.StatusId == 150L ? MyCommon.HITRESULT.Copy : MyCommon.HITRESULT.None));
374 this.tabinfo.AddTab(filterTab);
376 this.tabinfo.DistributePosts();
377 this.tabinfo.SubmitUpdate();
380 Assert.Equal(3, homeTab.UnreadCount);
382 // Recent タブのツイートをすべて未読にする
383 this.tabinfo.SetReadHomeTab();
385 // FilterHit が true である StatusId: 150 を除いてすべて未読になっている
386 Assert.Equal(1, homeTab.UnreadCount);
387 Assert.Equal(150L, homeTab.NextUnreadId);
391 public void SubmitUpdate_RemoveSubmit_Test()
393 var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
395 this.tabinfo.AddPost(new PostClass { StatusId = 100L });
396 this.tabinfo.DistributePosts();
397 this.tabinfo.SubmitUpdate();
399 Assert.Equal(1, homeTab.AllCount);
401 this.tabinfo.RemovePostFromAllTabs(100L, setIsDeleted: true);
404 Assert.Equal(1, homeTab.AllCount);
406 this.tabinfo.SubmitUpdate(out var soundFile, out var notifyPosts,
407 out var newMentionOrDm, out var isDeletePost);
409 Assert.True(isDeletePost);
410 Assert.Equal(0, homeTab.AllCount);
411 Assert.False(this.tabinfo.Posts.ContainsKey(100L));
415 public void SubmitUpdate_RemoveSubmit_NotOrphaned_Test()
417 var homeTab = this.tabinfo.GetTabByType<HomeTabModel>();
418 var favTab = this.tabinfo.GetTabByType<FavoritesTabModel>();
420 this.tabinfo.AddPost(new PostClass { StatusId = 100L, IsFav = true });
421 this.tabinfo.DistributePosts();
422 this.tabinfo.SubmitUpdate();
424 Assert.Equal(1, homeTab.AllCount);
425 Assert.Equal(1, favTab.AllCount);
427 // favTab のみ発言を除去 (homeTab には残ったまま)
428 favTab.EnqueueRemovePost(100L, setIsDeleted: false);
431 Assert.Equal(1, homeTab.AllCount);
432 Assert.Equal(1, favTab.AllCount);
434 this.tabinfo.SubmitUpdate(out var soundFile, out var notifyPosts,
435 out var newMentionOrDm, out var isDeletePost);
437 Assert.True(isDeletePost);
438 Assert.Equal(1, homeTab.AllCount);
439 Assert.Equal(0, favTab.AllCount);
441 // homeTab には発言が残っているので Posts からは削除されない
442 Assert.True(this.tabinfo.Posts.ContainsKey(100L));
446 public void SubmitUpdate_NotifyPriorityTest()
448 var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
449 homeTab.UnreadManage = true;
450 homeTab.SoundFile = "home.wav";
452 var replyTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Mentions);
453 replyTab.UnreadManage = true;
454 replyTab.SoundFile = "reply.wav";
456 var dmTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.DirectMessage);
457 dmTab.UnreadManage = true;
458 dmTab.SoundFile = "dm.wav";
461 this.tabinfo.AddPost(new PostClass { StatusId = 100L, IsRead = false });
464 this.tabinfo.AddPost(new PostClass { StatusId = 200L, IsReply = true, IsRead = false });
467 dmTab.AddPostQueue(new PostClass { StatusId = 300L, IsDm = true, IsRead = false });
469 this.tabinfo.DistributePosts();
471 this.tabinfo.SubmitUpdate(out var soundFile, out var notifyPosts,
472 out var newMentionOrDm, out var isDeletePost);
474 // DM が最も優先度が高いため DM の通知音が再生される
475 Assert.Equal("dm.wav", soundFile);
478 Assert.Equal(3, notifyPosts.Length);
482 public void SubmitUpdate_IgnoreEmptySoundPath_Test()
484 var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
485 homeTab.UnreadManage = true;
486 homeTab.SoundFile = "home.wav";
488 var replyTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Mentions);
489 replyTab.UnreadManage = true;
490 replyTab.SoundFile = "";
493 this.tabinfo.AddPost(new PostClass { StatusId = 100L, IsRead = false });
496 this.tabinfo.AddPost(new PostClass { StatusId = 200L, IsReply = true, IsRead = false });
498 this.tabinfo.DistributePosts();
500 this.tabinfo.SubmitUpdate(out var soundFile, out var notifyPosts,
501 out var newMentionOrDm, out var isDeletePost);
503 // リプライの方が通知音の優先度が高いが、replyTab.SoundFile が空文字列なので次点の Recent の通知音を鳴らす
504 Assert.Equal("home.wav", soundFile);
507 Assert.Equal(2, notifyPosts.Length);
511 public void FilterAll_CopyFilterTest()
513 var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
515 var myTab1 = new FilterTabModel("MyTab1");
516 this.tabinfo.AddTab(myTab1);
518 var filter = new PostFilterRule
526 myTab1.AddFilter(filter);
527 myTab1.FilterModified = false;
529 this.tabinfo.AddPost(new PostClass { StatusId = 100L, ScreenName = "aaa" });
530 this.tabinfo.AddPost(new PostClass { StatusId = 200L, ScreenName = "bbb" });
531 this.tabinfo.AddPost(new PostClass { StatusId = 300L, ScreenName = "ccc" });
532 this.tabinfo.DistributePosts();
533 this.tabinfo.SubmitUpdate();
536 Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
537 Assert.Equal(new[] { 100L }, myTab1.StatusIds);
540 filter.FilterName = "bbb";
543 this.tabinfo.FilterAll();
544 this.tabinfo.DistributePosts();
545 this.tabinfo.SubmitUpdate();
548 // [statusId: 100] は MyTab1 から取り除かれる
549 // [statusId: 200] は Recent から MyTab1 にコピーされる
552 Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
553 Assert.Equal(new[] { 200L }, myTab1.StatusIds);
557 public void FilterAll_CopyAndMarkFilterTest()
559 var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
561 var myTab1 = new FilterTabModel("MyTab1");
562 this.tabinfo.AddTab(myTab1);
564 var filter = new PostFilterRule
572 myTab1.AddFilter(filter);
573 myTab1.FilterModified = false;
575 this.tabinfo.AddPost(new PostClass { StatusId = 100L, ScreenName = "aaa" });
576 this.tabinfo.AddPost(new PostClass { StatusId = 200L, ScreenName = "bbb" });
577 this.tabinfo.AddPost(new PostClass { StatusId = 300L, ScreenName = "ccc" });
578 this.tabinfo.DistributePosts();
579 this.tabinfo.SubmitUpdate();
582 Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
583 Assert.Equal(new[] { 100L }, myTab1.StatusIds);
586 filter.FilterName = "bbb";
589 this.tabinfo.FilterAll();
590 this.tabinfo.DistributePosts();
591 this.tabinfo.SubmitUpdate();
594 // [statusId: 100] は MyTab1 から取り除かれる
595 // [statusId: 200] は Recent から MyTab1 にコピーされ、マークが付与される
598 Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
599 Assert.Equal(new[] { 200L }, myTab1.StatusIds);
601 // [statusId: 200] は IsMark が true の状態になる
602 Assert.True(this.tabinfo[200L].IsMark);
606 public void FilterAll_MoveFilterTest()
608 var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
610 var myTab1 = new FilterTabModel("MyTab1");
611 this.tabinfo.AddTab(myTab1);
613 var filter = new PostFilterRule
620 myTab1.AddFilter(filter);
621 myTab1.FilterModified = false;
623 this.tabinfo.AddPost(new PostClass { StatusId = 100L, ScreenName = "aaa" });
624 this.tabinfo.AddPost(new PostClass { StatusId = 200L, ScreenName = "bbb" });
625 this.tabinfo.AddPost(new PostClass { StatusId = 300L, ScreenName = "ccc" });
626 this.tabinfo.DistributePosts();
627 this.tabinfo.SubmitUpdate();
630 Assert.Equal(new[] { 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
631 Assert.Equal(new[] { 100L }, myTab1.StatusIds);
634 filter.FilterName = "bbb";
637 this.tabinfo.FilterAll();
638 this.tabinfo.DistributePosts();
639 this.tabinfo.SubmitUpdate();
642 // [statusId: 100] は MyTab1 から取り除かれて Recent に戻される
643 // [statusId: 200] は Recent から MyTab1 に移動される
646 Assert.Equal(new[] { 100L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
647 Assert.Equal(new[] { 200L }, myTab1.StatusIds);
651 public void FilterAll_MoveFilterTest2()
653 var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
655 var myTab1 = new FilterTabModel("MyTab1");
656 var myTab2 = new FilterTabModel("MyTab2");
657 this.tabinfo.AddTab(myTab1);
658 this.tabinfo.AddTab(myTab2);
660 var filter1 = new PostFilterRule
667 myTab1.AddFilter(filter1);
668 myTab1.FilterModified = false;
670 var filter2 = new PostFilterRule
677 myTab2.AddFilter(filter2);
678 myTab2.FilterModified = false;
680 this.tabinfo.AddPost(new PostClass { StatusId = 100L, ScreenName = "aaa" });
681 this.tabinfo.AddPost(new PostClass { StatusId = 200L, ScreenName = "bbb" });
682 this.tabinfo.AddPost(new PostClass { StatusId = 300L, ScreenName = "ccc" });
683 this.tabinfo.DistributePosts();
684 this.tabinfo.SubmitUpdate();
687 Assert.Equal(new[] { 300L }, homeTab.StatusIds);
688 Assert.Equal(new[] { 100L }, myTab1.StatusIds);
689 Assert.Equal(new[] { 200L }, myTab2.StatusIds);
692 filter1.FilterName = "bbb";
695 filter2.FilterName = "ccc";
698 this.tabinfo.FilterAll();
699 this.tabinfo.DistributePosts();
700 this.tabinfo.SubmitUpdate();
703 // [statusId: 100] は MyTab1 から取り除かれて Recent に戻される
704 // [statusId: 200] は MyTab1 に移動される
705 // [statusId: 200] は MyTab2 から取り除かれるが MyTab1 に移動されているので Recent には戻さない
706 // [statusId: 300] は Recent から MyTab2 に移動される
709 Assert.Equal(new[] { 100L }, homeTab.StatusIds);
710 Assert.Equal(new[] { 200L }, myTab1.StatusIds);
711 Assert.Equal(new[] { 300L }, myTab2.StatusIds);
715 public void FilterAll_ExcludeReplyFilterTest()
717 var homeTab = this.tabinfo.GetTabByType<HomeTabModel>();
718 var replyTab = this.tabinfo.GetTabByType<MentionsTabModel>();
720 var filter = new PostFilterRule
722 // @aaa からのリプライは Reply タブに振り分けない
723 ExFilterName = "aaa",
725 replyTab.AddFilter(filter);
726 replyTab.FilterModified = false;
728 this.tabinfo.AddPost(new PostClass { StatusId = 100L, ScreenName = "aaa", IsReply = true });
729 this.tabinfo.AddPost(new PostClass { StatusId = 200L, ScreenName = "bbb", IsReply = true });
730 this.tabinfo.AddPost(new PostClass { StatusId = 300L, ScreenName = "ccc", IsReply = true });
731 this.tabinfo.DistributePosts();
732 this.tabinfo.SubmitUpdate();
735 Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
736 Assert.Equal(new[] { 200L, 300L }, replyTab.StatusIds, AnyOrderComparer<long>.Instance);
738 // [statusId: 100] は IsExcludeReply が true の状態になっている
739 Assert.True(this.tabinfo[100L].IsExcludeReply);
742 filter.ExFilterName = "bbb";
745 this.tabinfo.FilterAll();
746 this.tabinfo.DistributePosts();
747 this.tabinfo.SubmitUpdate();
750 // [statusId: 100] は Reply にコピーされ、IsExcludeReply が false になる
751 // [statusId: 200] は Reply から取り除かれ、IsExcludeReply が true になる
754 Assert.Equal(new[] { 100L, 200L, 300L }, homeTab.StatusIds, AnyOrderComparer<long>.Instance);
755 Assert.Equal(new[] { 100L, 300L }, replyTab.StatusIds, AnyOrderComparer<long>.Instance);
757 // [statusId: 100] は IsExcludeReply が false の状態になる
758 Assert.False(this.tabinfo[100L].IsExcludeReply);
760 // [statusId: 200] は IsExcludeReply が true の状態になる
761 Assert.True(this.tabinfo[200L].IsExcludeReply);
764 class TestPostFilterRule : PostFilterRule
766 public static PostFilterRule Create(Func<PostClass, MyCommon.HITRESULT> filterDelegate)
768 return new TestPostFilterRule
770 FilterDelegate = filterDelegate,