OSDN Git Service

#30840 言語間リンクの取得をMediaWiki APIより行うよう変更,
[wptscs/wpts.git] / WptscsTest / Websites / MediaWikiPageTest.cs
1 // ================================================================================================
2 // <summary>
3 //      MediaWikiPageのテストクラスソース。</summary>
4 //
5 // <copyright file="MediaWikiPageTest.cs" company="honeplusのメモ帳">
6 //      Copyright (C) 2013 Honeplus. All rights reserved.</copyright>
7 // <author>
8 //      Honeplus</author>
9 // ================================================================================================
10
11 namespace Honememo.Wptscs.Websites
12 {
13     using System;
14     using System.Collections.Generic;
15     using System.IO;
16     using System.Xml.Linq;
17     using Honememo.Parsers;
18     using Honememo.Utilities;
19     using Honememo.Wptscs.Models;
20     using Honememo.Wptscs.Parsers;
21     using Microsoft.VisualStudio.TestTools.UnitTesting;
22
23     /// <summary>
24     /// <see cref="MediaWikiPage"/>のテストクラスです。
25     /// </summary>
26     [TestClass]
27     public class MediaWikiPageTest
28     {
29         #region 定数
30
31         /// <summary>
32         /// example.xmlのページ本文。
33         /// </summary>
34         private static readonly string exampleText
35             = "[[File:Example.png|thumb|Wikipedia's example image. (Example.png)]]\n{{wiktionary}}\n{{wikiquote}}\n"
36                 + "'''Example''' may refer to:\n\n*[[Example (rapper)]], a British rapper\n*[[example.com]], "
37                 + "[[example.net]], [[example.org]]  and [[.example]], domain names reserved for use in documentation "
38                 + "as examples \n\n==See also==\n*[[Exemplum]], medieval collections of short stories to be told in "
39                 + "sermons\n*[[Exemplar]], a prototype or model which others can use to understand a topic better\n\n"
40                 + "{{disambig}}\n\n[[fr:Example]]\n[[ksh:Example (Watt ėßß datt?)]]";
41         
42         /// <summary>
43         /// example.xmlのページ本文。
44         /// </summary>
45         private static readonly DateTime exampleTimestamp = DateTime.Parse("2010-07-13T00:49:18Z");
46
47         #endregion
48
49         #region プロパティテストケース
50
51         /// <summary>
52         /// <see cref="MediaWikiPage.Text"/>プロパティテストケース。
53         /// </summary>
54         [TestMethod]
55         public void TestText()
56         {
57             // 何も値が設定されていない場合、記事名からデータを読み込みその本文を返す
58             // 同時にタイムスタンプ, URIも設定される
59             // ※ 異常系については、MediaWiki側の実装なのでそちらでテストする
60             MediaWiki site = new MockFactory().GetMediaWiki("en");
61             Uri uri = new Uri(new Uri(site.Location), StringUtils.FormatDollarVariable(site.ExportPath, "example"));
62             MediaWikiPageMock page = new MediaWikiPageMock(site, "example");
63             Assert.IsNull(page.Uri);
64
65             Assert.AreEqual(MediaWikiPageTest.exampleText, page.Text);
66             Assert.AreEqual(MediaWikiPageTest.exampleTimestamp, page.Timestamp);
67             Assert.AreEqual(uri, page.Uri);
68
69             // 一度読み込むと、次回以降はその値が設定されている
70             page.Title = "new name";
71             Assert.AreEqual(MediaWikiPageTest.exampleText, page.Text);
72             Assert.AreEqual(MediaWikiPageTest.exampleTimestamp, page.Timestamp);
73
74             // 値が設定されている状態では、設定された値が返る
75             page = new MediaWikiPageMock(site, "example");
76             page.Text = "test body";
77             Assert.AreEqual("test body", page.Text);
78             Assert.IsNull(page.Uri);
79         }
80
81         /// <summary>
82         /// <see cref="MediaWikiPage.Timestamp"/>プロパティテストケース。
83         /// </summary>
84         [TestMethod]
85         public void TestTimestamp()
86         {
87             // 何も値が設定されていない場合、記事名からデータを読み込みそのタイムスタンプを返す
88             // 同時にページ本文, URIも設定される
89             // ※ 異常系については、MediaWiki側の実装なのでそちらでテストする
90             MediaWiki site = new MockFactory().GetMediaWiki("en");
91             Uri uri = new Uri(new Uri(site.Location), StringUtils.FormatDollarVariable(site.ExportPath, "example"));
92             MediaWikiPageMock page = new MediaWikiPageMock(site, "example");
93             Assert.IsNull(page.Uri);
94
95             Assert.AreEqual(MediaWikiPageTest.exampleTimestamp, page.Timestamp);
96             Assert.AreEqual(MediaWikiPageTest.exampleText, page.Text);
97             Assert.AreEqual(uri, page.Uri);
98
99             // 一度読み込むと、次回以降はその値が設定されている
100             page.Title = "new name";
101             Assert.AreEqual(MediaWikiPageTest.exampleTimestamp, page.Timestamp);
102             Assert.AreEqual(MediaWikiPageTest.exampleText, page.Text);
103
104             // 値が設定されている状態では、設定された値が返る
105             page = new MediaWikiPageMock(site, "example");
106             DateTime now = DateTime.Now;
107             page.Timestamp = now;
108             Assert.AreEqual(now, page.Timestamp);
109             Assert.IsNull(page.Uri);
110         }
111
112         #endregion
113
114         #region 静的メソッドテストケース
115
116         /// <summary>
117         /// <see cref="MediaWikiPage.GetFromQuery"/>メソッドテストケース。
118         /// </summary>
119         [TestMethod]
120         public void TestGetFromQuery()
121         {
122             // XMLを変えつつ、クエリーから想定通りのパラメータが読み込まれていることを確認
123             // ※ ページ本文とタイムスタンプはnullだが遅延読み込みされるので、ここではチェックしない
124             // ※ XMLはいろんなパターンがありえるが、パターンが増えすぎるので使う項目しかテストしていない。
125             //    ここ以外の項目は、基本的に影響していない・・・はず。
126
127             // 必要最小限のパターン
128             MediaWiki website = new MockFactory().GetMediaWiki("en");
129             XElement pe = new XElement("page", new XAttribute("title", "Test page"));
130             XElement query = new XElement("query", new XElement("pages", pe));
131             MediaWikiPage page = MediaWikiPage.GetFromQuery(website, null, query);
132             Assert.AreSame(website, page.Website);
133             Assert.IsNull(page.Uri);
134             Assert.AreEqual("Test page", page.Title);
135             Assert.IsNull(page.GetInterlanguage("ja"));
136             Assert.IsNull(page.GetInterlanguage("de"));
137             Assert.IsNull(page.Redirect);
138
139             // URI
140             Uri uri = new Uri("http://example.com/");
141             page = MediaWikiPage.GetFromQuery(website, uri, query);
142             Assert.AreSame(website, page.Website);
143             Assert.AreSame(uri, page.Uri);
144             Assert.AreEqual("Test page", page.Title);
145             Assert.IsNull(page.GetInterlanguage("ja"));
146             Assert.IsNull(page.GetInterlanguage("de"));
147             Assert.IsNull(page.Redirect);
148
149             // 言語間リンク枠だけ、上と変わらず
150             XElement les = new XElement("langlinks");
151             pe.Add(les);
152             page = MediaWikiPage.GetFromQuery(website, uri, query);
153             Assert.AreSame(website, page.Website);
154             Assert.AreSame(uri, page.Uri);
155             Assert.AreEqual("Test page", page.Title);
156             Assert.IsNull(page.GetInterlanguage("ja"));
157             Assert.IsNull(page.GetInterlanguage("de"));
158             Assert.IsNull(page.Redirect);
159
160             // 言語間リンク
161             les.Add(new XElement("ll", new XAttribute("lang", "ja"), "テストページ"));
162             page = MediaWikiPage.GetFromQuery(website, uri, query);
163             Assert.AreSame(website, page.Website);
164             Assert.AreSame(uri, page.Uri);
165             Assert.AreEqual("Test page", page.Title);
166             Assert.AreEqual("テストページ", page.GetInterlanguage("ja"));
167             Assert.IsNull(page.GetInterlanguage("de"));
168             Assert.IsNull(page.Redirect);
169
170             // 言語間リンク複数も可
171             les.Add(new XElement("ll", new XAttribute("lang", "de"), "Test de page"));
172             page = MediaWikiPage.GetFromQuery(website, uri, query);
173             Assert.AreSame(website, page.Website);
174             Assert.AreSame(uri, page.Uri);
175             Assert.AreEqual("Test page", page.Title);
176             Assert.AreEqual("テストページ", page.GetInterlanguage("ja"));
177             Assert.AreEqual("Test de page", page.GetInterlanguage("de"));
178             Assert.IsNull(page.Redirect);
179
180             // リダイレクト
181             query.Add(new XElement("redirects", new XElement("r", new XAttribute("from", "from Redirect"))));
182             page = MediaWikiPage.GetFromQuery(website, uri, query);
183             Assert.AreSame(website, page.Website);
184             Assert.AreSame(uri, page.Uri);
185             Assert.AreEqual("Test page", page.Title);
186             Assert.AreEqual("テストページ", page.GetInterlanguage("ja"));
187             Assert.AreEqual("Test de page", page.GetInterlanguage("de"));
188             Assert.AreEqual("from Redirect", page.Redirect);
189         }
190
191         /// <summary>
192         /// <see cref="MediaWikiPage.GetFromQuery"/>メソッドテストケース(サイトが<c>null</c>)。
193         /// </summary>
194         [TestMethod]
195         [ExpectedException(typeof(ArgumentNullException))]
196         public void TestGetFromQueryAboutWebsiteIsNull()
197         {
198             MediaWikiPage.GetFromQuery(
199                 null,
200                 null,
201                 new XElement(
202                     "query",
203                     new XElement(
204                         "pages",
205                         new XElement("page", new XAttribute("title", "Test page")))));
206         }
207
208         /// <summary>
209         /// <see cref="MediaWikiPage.GetFromQuery"/>メソッドテストケース(XML不正)。
210         /// </summary>
211         [TestMethod]
212         [ExpectedException(typeof(InvalidOperationException))]
213         public void TestGetFromQueryAboutPageElementIsNotFound()
214         {
215             MediaWikiPage.GetFromQuery(
216                 new MockFactory().GetMediaWiki("en"),
217                 null,
218                 new XElement("query", new XElement("pages")));
219         }
220
221         /// <summary>
222         /// <see cref="MediaWikiPage.GetFromQuery"/>メソッドテストケース(ページなし)。
223         /// </summary>
224         [TestMethod]
225         [ExpectedException(typeof(FileNotFoundException))]
226         public void TestGetFromQueryAboutMissingPage()
227         {
228             MediaWikiPage.GetFromQuery(
229                 new MockFactory().GetMediaWiki("en"),
230                 null,
231                 new XElement(
232                     "query",
233                     new XElement(
234                         "pages",
235                         new XElement(
236                             "page",
237                             new XAttribute("title", "Test page"),
238                             new XAttribute("missing", string.Empty)))));
239         }
240
241         #endregion
242
243         #region 公開メソッドテストケース
244
245         /// <summary>
246         /// <see cref="MediaWikiPage.GetInterlanguage"/>メソッドテストケース。
247         /// </summary>
248         [TestMethod]
249         public void TestGetInterlanguage()
250         {
251             MediaWikiPageMock page = new MediaWikiPageMock(
252                 new MockFactory().GetMediaWiki("en"),
253                 "TestTitle");
254             page.Interlanguages.Add("ja", "テストページ");
255             page.Interlanguages.Add("fr", "Test_Fr");
256             Assert.AreEqual("テストページ", page.GetInterlanguage("ja"));
257             Assert.AreEqual("Test_Fr", page.GetInterlanguage("fr"));
258             Assert.IsNull(page.GetInterlanguage("de"));
259             Assert.IsNull(page.GetInterlanguage("ru"));
260             Assert.IsNull(page.GetInterlanguage("zh"));
261         }
262
263         /// <summary>
264         /// <see cref="MediaWikiPage.IsRedirect"/>メソッドテストケース。
265         /// </summary>
266         [TestMethod]
267         public void TestIsRedirect()
268         {
269             MediaWiki site = new MediaWiki(new Language("en"));
270             MediaWikiPage page = new MediaWikiPage(site, "TestTitle");
271             Assert.IsFalse(page.IsRedirect());
272             Assert.IsNull(page.Redirect);
273
274             page.Redirect = "Test Redirect";
275             Assert.IsTrue(page.IsRedirect());
276             Assert.AreEqual("Test Redirect", page.Redirect);
277
278             page.Redirect = string.Empty;
279             Assert.IsTrue(page.IsRedirect());
280             Assert.AreEqual(string.Empty, page.Redirect);
281
282             page.Redirect = null;
283             Assert.IsFalse(page.IsRedirect());
284             Assert.IsNull(page.Redirect);
285         }
286
287         /// <summary>
288         /// <see cref="MediaWikiPage.Normalize"/>メソッドテストケース。
289         /// </summary>
290         [TestMethod]
291         public void TestNormalize()
292         {
293             MediaWiki site = new MockFactory().GetMediaWiki("en");
294             MediaWikiPage page = new MediaWikiPage(site, "A/b/c");
295
296             // サブページの正規化
297             Assert.AreEqual("Normal page", page.Normalize(new MediaWikiLink("Normal page")));
298             Assert.AreEqual("A/b/c/s", page.Normalize(new MediaWikiLink("/s")));
299             Assert.AreEqual("A/b/c/s", page.Normalize(new MediaWikiLink("/s/")));
300             Assert.AreEqual("A/b", page.Normalize(new MediaWikiLink("../")));
301             Assert.AreEqual("A", page.Normalize(new MediaWikiLink("../../")));
302             Assert.AreEqual("A/b/s", page.Normalize(new MediaWikiLink("../s")));
303             Assert.AreEqual("A/b/s", page.Normalize(new MediaWikiLink("../s/")));
304             Assert.AreEqual("A/s", page.Normalize(new MediaWikiLink("../../s")));
305             Assert.AreEqual("A/s", page.Normalize(new MediaWikiLink("../../s/")));
306
307             // テンプレートの正規化
308             Assert.AreEqual("Template:Template page", page.Normalize(new MediaWikiTemplate("Template page")));
309             Assert.AreEqual("Normal page", page.Normalize(new MediaWikiTemplate("Normal page") { IsColon = true }));
310             Assert.AreEqual("Wikipedia:Help page", page.Normalize(new MediaWikiTemplate("Wikipedia:Help page")));
311             Assert.AreEqual("template:Template page", page.Normalize(new MediaWikiTemplate("template:Template page")));
312             Assert.AreEqual("A/b/c/Doc", page.Normalize(new MediaWikiTemplate("/Doc")));
313             Assert.AreEqual("CURRENTYEAR", page.Normalize(new MediaWikiTemplate("CURRENTYEAR")));
314         }
315
316         #endregion
317
318         #region モッククラス
319
320         /// <summary>
321         /// <see cref="MediaWikiPage"/>テスト用のモッククラスです。
322         /// </summary>
323         private class MediaWikiPageMock : MediaWikiPage
324         {
325             #region コンストラクタ
326
327             /// <summary>
328             /// コンストラクタ。
329             /// ページの本文, タイムスタンプには<c>null</c>を設定。
330             /// </summary>
331             /// <param name="website">ページが所属するウェブサイト。</param>
332             /// <param name="title">ページタイトル。</param>
333             public MediaWikiPageMock(MediaWiki website, string title)
334                 : base(website, title)
335             {
336             }
337
338             #endregion
339
340             #region 非公開プロパティテスト用のオーラーライドプロパティ
341
342
343             /// <summary>
344             /// ページタイトル。
345             /// </summary>
346             public new string Title
347             {
348                 get
349                 {
350                     return base.Title;
351                 }
352
353                 set
354                 {
355                     base.Title = value;
356                 }
357             }
358
359             /// <summary>
360             /// ページの本文。
361             /// </summary>
362             public new string Text
363             {
364                 get
365                 {
366                     return base.Text;
367                 }
368
369                 set
370                 {
371                     base.Text = value;
372                 }
373             }
374
375             /// <summary>
376             /// ページのタイムスタンプ。
377             /// </summary>
378             public new DateTime? Timestamp
379             {
380                 get
381                 {
382                     return base.Timestamp;
383                 }
384
385                 set
386                 {
387                     base.Timestamp = value;
388                 }
389             }
390
391             /// <summary>
392             /// 言語間リンクの対応表。
393             /// </summary>
394             public new IDictionary<string, string> Interlanguages
395             {
396                 get
397                 {
398                     return base.Interlanguages;
399                 }
400             }
401
402             #endregion
403         }
404
405         #endregion
406     }
407 }