atom_10_test.go 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528
  1. // Copyright 2019 Frédéric Guillot. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package atom // import "miniflux.app/reader/atom"
  5. import (
  6. "bytes"
  7. "testing"
  8. "time"
  9. )
  10. func TestParseAtomSample(t *testing.T) {
  11. data := `<?xml version="1.0" encoding="utf-8"?>
  12. <feed xmlns="http://www.w3.org/2005/Atom">
  13. <title>Example Feed</title>
  14. <link href="http://example.org/"/>
  15. <updated>2003-12-13T18:30:02Z</updated>
  16. <author>
  17. <name>John Doe</name>
  18. </author>
  19. <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
  20. <entry>
  21. <title>Atom-Powered Robots Run Amok</title>
  22. <link href="http://example.org/2003/12/13/atom03"/>
  23. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  24. <updated>2003-12-13T18:30:02Z</updated>
  25. <summary>Some text.</summary>
  26. </entry>
  27. </feed>`
  28. feed, err := Parse("http://example.org/feed.xml", bytes.NewBufferString(data))
  29. if err != nil {
  30. t.Fatal(err)
  31. }
  32. if feed.Title != "Example Feed" {
  33. t.Errorf("Incorrect title, got: %s", feed.Title)
  34. }
  35. if feed.FeedURL != "http://example.org/feed.xml" {
  36. t.Errorf("Incorrect feed URL, got: %s", feed.FeedURL)
  37. }
  38. if feed.SiteURL != "http://example.org/" {
  39. t.Errorf("Incorrect site URL, got: %s", feed.SiteURL)
  40. }
  41. if len(feed.Entries) != 1 {
  42. t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries))
  43. }
  44. if !feed.Entries[0].Date.Equal(time.Date(2003, time.December, 13, 18, 30, 2, 0, time.UTC)) {
  45. t.Errorf("Incorrect entry date, got: %v", feed.Entries[0].Date)
  46. }
  47. if feed.Entries[0].Hash != "3841e5cf232f5111fc5841e9eba5f4b26d95e7d7124902e0f7272729d65601a6" {
  48. t.Errorf("Incorrect entry hash, got: %s", feed.Entries[0].Hash)
  49. }
  50. if feed.Entries[0].URL != "http://example.org/2003/12/13/atom03" {
  51. t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL)
  52. }
  53. if feed.Entries[0].CommentsURL != "" {
  54. t.Errorf("Incorrect entry Comments URL, got: %s", feed.Entries[0].CommentsURL)
  55. }
  56. if feed.Entries[0].Title != "Atom-Powered Robots Run Amok" {
  57. t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title)
  58. }
  59. if feed.Entries[0].Content != "Some text." {
  60. t.Errorf("Incorrect entry content, got: %s", feed.Entries[0].Content)
  61. }
  62. if feed.Entries[0].Author != "John Doe" {
  63. t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author)
  64. }
  65. }
  66. func TestParseFeedWithoutTitle(t *testing.T) {
  67. data := `<?xml version="1.0" encoding="utf-8"?>
  68. <feed xmlns="http://www.w3.org/2005/Atom">
  69. <link rel="alternate" type="text/html" href="https://example.org/"/>
  70. <link rel="self" type="application/atom+xml" href="https://example.org/feed"/>
  71. <updated>2003-12-13T18:30:02Z</updated>
  72. </feed>`
  73. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  74. if err != nil {
  75. t.Fatal(err)
  76. }
  77. if feed.Title != "https://example.org/" {
  78. t.Errorf("Incorrect feed title, got: %s", feed.Title)
  79. }
  80. }
  81. func TestParseEntryWithoutTitleButWithURL(t *testing.T) {
  82. data := `<?xml version="1.0" encoding="utf-8"?>
  83. <feed xmlns="http://www.w3.org/2005/Atom">
  84. <title>Example Feed</title>
  85. <link href="http://example.org/"/>
  86. <updated>2003-12-13T18:30:02Z</updated>
  87. <author>
  88. <name>John Doe</name>
  89. </author>
  90. <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
  91. <entry>
  92. <link href="http://example.org/2003/12/13/atom03"/>
  93. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  94. <updated>2003-12-13T18:30:02Z</updated>
  95. </entry>
  96. </feed>`
  97. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  98. if err != nil {
  99. t.Fatal(err)
  100. }
  101. if feed.Entries[0].Title != "http://example.org/2003/12/13/atom03" {
  102. t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title)
  103. }
  104. }
  105. func TestParseEntryWithoutTitleButWithSummary(t *testing.T) {
  106. data := `<?xml version="1.0" encoding="utf-8"?>
  107. <feed xmlns="http://www.w3.org/2005/Atom">
  108. <title>Example Feed</title>
  109. <link href="http://example.org/"/>
  110. <updated>2003-12-13T18:30:02Z</updated>
  111. <author>
  112. <name>John Doe</name>
  113. </author>
  114. <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
  115. <entry>
  116. <link href="http://example.org/2003/12/13/atom03"/>
  117. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  118. <updated>2003-12-13T18:30:02Z</updated>
  119. <summary>Some text.</summary>
  120. </entry>
  121. </feed>`
  122. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  123. if err != nil {
  124. t.Fatal(err)
  125. }
  126. if feed.Entries[0].Title != "Some text." {
  127. t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title)
  128. }
  129. }
  130. func TestParseEntryWithoutTitleButWithXHTMLContent(t *testing.T) {
  131. data := `<?xml version="1.0" encoding="utf-8"?>
  132. <feed xmlns="http://www.w3.org/2005/Atom">
  133. <title>Example Feed</title>
  134. <link href="http://example.org/"/>
  135. <updated>2003-12-13T18:30:02Z</updated>
  136. <author>
  137. <name>John Doe</name>
  138. </author>
  139. <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
  140. <entry>
  141. <link href="http://example.org/2003/12/13/atom03"/>
  142. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  143. <updated>2003-12-13T18:30:02Z</updated>
  144. <content type="xhtml">
  145. <div xmlns="http://www.w3.org/1999/xhtml">AT&amp;T bought <b>by SBC</b>!</div>
  146. </content>
  147. </entry>
  148. </feed>`
  149. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  150. if err != nil {
  151. t.Fatal(err)
  152. }
  153. if feed.Entries[0].Title != "AT&T bought by SBC!" {
  154. t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title)
  155. }
  156. }
  157. func TestParseFeedURL(t *testing.T) {
  158. data := `<?xml version="1.0" encoding="utf-8"?>
  159. <feed xmlns="http://www.w3.org/2005/Atom">
  160. <title>Example Feed</title>
  161. <link rel="alternate" type="text/html" href="https://example.org/"/>
  162. <link rel="self" type="application/atom+xml" href="https://example.org/feed"/>
  163. <updated>2003-12-13T18:30:02Z</updated>
  164. </feed>`
  165. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  166. if err != nil {
  167. t.Fatal(err)
  168. }
  169. if feed.SiteURL != "https://example.org/" {
  170. t.Errorf("Incorrect site URL, got: %s", feed.SiteURL)
  171. }
  172. if feed.FeedURL != "https://example.org/feed" {
  173. t.Errorf("Incorrect feed URL, got: %s", feed.FeedURL)
  174. }
  175. }
  176. func TestParseFeedWithRelativeURL(t *testing.T) {
  177. data := `<?xml version="1.0" encoding="utf-8"?>
  178. <feed xmlns="http://www.w3.org/2005/Atom">
  179. <title>Example Feed</title>
  180. <link href="/blog/atom.xml" rel="self" type="application/atom+xml"/>
  181. <link href="/blog"/>
  182. <entry>
  183. <title>Test</title>
  184. <link href="/blog/article.html"/>
  185. <link href="/blog/article.html" rel="alternate" type="text/html"/>
  186. <id>/blog/article.html</id>
  187. <updated>2003-12-13T18:30:02Z</updated>
  188. <summary>Some text.</summary>
  189. </entry>
  190. </feed>`
  191. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  192. if err != nil {
  193. t.Fatal(err)
  194. }
  195. if feed.FeedURL != "https://example.org/blog/atom.xml" {
  196. t.Errorf("Incorrect feed URL, got: %s", feed.FeedURL)
  197. }
  198. if feed.SiteURL != "https://example.org/blog" {
  199. t.Errorf("Incorrect site URL, got: %s", feed.SiteURL)
  200. }
  201. if feed.Entries[0].URL != "https://example.org/blog/article.html" {
  202. t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL)
  203. }
  204. }
  205. func TestParseEntryWithRelativeURL(t *testing.T) {
  206. data := `<?xml version="1.0" encoding="utf-8"?>
  207. <feed xmlns="http://www.w3.org/2005/Atom">
  208. <title>Example Feed</title>
  209. <link href="http://example.org/"/>
  210. <entry>
  211. <title>Test</title>
  212. <link href="something.html"/>
  213. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  214. <updated>2003-12-13T18:30:02Z</updated>
  215. <summary>Some text.</summary>
  216. </entry>
  217. </feed>`
  218. feed, err := Parse("https://example.net/", bytes.NewBufferString(data))
  219. if err != nil {
  220. t.Fatal(err)
  221. }
  222. if feed.Entries[0].URL != "http://example.org/something.html" {
  223. t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL)
  224. }
  225. }
  226. func TestParseEntryTitleWithWhitespaces(t *testing.T) {
  227. data := `<?xml version="1.0" encoding="utf-8"?>
  228. <feed xmlns="http://www.w3.org/2005/Atom">
  229. <title>Example Feed</title>
  230. <link href="http://example.org/"/>
  231. <entry>
  232. <title>
  233. Some Title
  234. </title>
  235. <link href="http://example.org/2003/12/13/atom03"/>
  236. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  237. <updated>2003-12-13T18:30:02Z</updated>
  238. <summary>Some text.</summary>
  239. </entry>
  240. </feed>`
  241. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  242. if err != nil {
  243. t.Fatal(err)
  244. }
  245. if feed.Entries[0].Title != "Some Title" {
  246. t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title)
  247. }
  248. }
  249. func TestParseEntryWithPlainTextTitle(t *testing.T) {
  250. data := `<?xml version="1.0" encoding="utf-8"?>
  251. <feed xmlns="http://www.w3.org/2005/Atom">
  252. <title>Example Feed</title>
  253. <link href="http://example.org/"/>
  254. <entry>
  255. <title type="text">AT&amp;T bought by SBC!</title>
  256. <link href="http://example.org/2003/12/13/atom03"/>
  257. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  258. <updated>2003-12-13T18:30:02Z</updated>
  259. <summary>Some text.</summary>
  260. </entry>
  261. <entry>
  262. <title>AT&amp;T bought by SBC!</title>
  263. <link href="http://example.org/2003/12/13/atom03"/>
  264. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  265. <updated>2003-12-13T18:30:02Z</updated>
  266. <summary>Some text.</summary>
  267. </entry>
  268. </feed>`
  269. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  270. if err != nil {
  271. t.Fatal(err)
  272. }
  273. expected := `AT&T bought by SBC!`
  274. for i := 0; i < 2; i++ {
  275. if feed.Entries[i].Title != expected {
  276. t.Errorf("Incorrect title for entry #%d, got: %q", i, feed.Entries[i].Title)
  277. }
  278. }
  279. }
  280. func TestParseEntryWithHTMLTitle(t *testing.T) {
  281. data := `<?xml version="1.0" encoding="utf-8"?>
  282. <feed xmlns="http://www.w3.org/2005/Atom">
  283. <title>Example Feed</title>
  284. <link href="http://example.org/"/>
  285. <entry>
  286. <title type="html">&lt;code&gt;Test&lt;/code&gt; Test</title>
  287. <link href="http://example.org/2003/12/13/atom03"/>
  288. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  289. <updated>2003-12-13T18:30:02Z</updated>
  290. <summary>Some text.</summary>
  291. </entry>
  292. <entry>
  293. <title type="html"><![CDATA[Test &#8220;Test&#8221;]]></title>
  294. <link href="http://example.org/2003/12/13/atom03"/>
  295. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  296. <updated>2003-12-13T18:30:02Z</updated>
  297. <summary>Some text.</summary>
  298. </entry>
  299. <entry>
  300. <title>
  301. <![CDATA[Entry title with space around CDATA]]>
  302. </title>
  303. <link href="http://example.org/2003/12/13/atom03"/>
  304. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  305. <updated>2003-12-13T18:30:02Z</updated>
  306. <summary>Some text.</summary>
  307. </entry>
  308. </feed>`
  309. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  310. if err != nil {
  311. t.Fatal(err)
  312. }
  313. if feed.Entries[0].Title != "<code>Test</code> Test" {
  314. t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title)
  315. }
  316. if feed.Entries[1].Title != "Test “Test”" {
  317. t.Errorf("Incorrect entry title, got: %q", feed.Entries[1].Title)
  318. }
  319. if feed.Entries[2].Title != "Entry title with space around CDATA" {
  320. t.Errorf("Incorrect entry title, got: %q", feed.Entries[2].Title)
  321. }
  322. }
  323. func TestParseEntryWithXHTMLTitle(t *testing.T) {
  324. data := `<?xml version="1.0" encoding="utf-8"?>
  325. <feed xmlns="http://www.w3.org/2005/Atom">
  326. <title>Example Feed</title>
  327. <link href="http://example.org/"/>
  328. <entry>
  329. <title type="xhtml">
  330. <div xmlns="http://www.w3.org/1999/xhtml">
  331. This is <b>XHTML</b> content.
  332. </div>
  333. </title>
  334. <link href="http://example.org/b"/>
  335. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  336. <updated>2003-12-13T18:30:02Z</updated>
  337. <summary>Some text.</summary>
  338. </entry>
  339. </feed>`
  340. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  341. if err != nil {
  342. t.Fatal(err)
  343. }
  344. if feed.Entries[0].Title != `This is <b>XHTML</b> content.` {
  345. t.Errorf("Incorrect entry title, got: %q", feed.Entries[1].Title)
  346. }
  347. }
  348. func TestParseEntryWithEmptyXHTMLTitle(t *testing.T) {
  349. data := `<?xml version="1.0" encoding="utf-8"?>
  350. <feed xmlns="http://www.w3.org/2005/Atom">
  351. <title>Example Feed</title>
  352. <link href="http://example.org/"/>
  353. <entry>
  354. <title type="xhtml">
  355. <div xmlns="http://www.w3.org/1999/xhtml"/>
  356. </title>
  357. <link href="http://example.org/entry"/>
  358. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  359. <updated>2003-12-13T18:30:02Z</updated>
  360. </entry>
  361. </feed>`
  362. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  363. if err != nil {
  364. t.Fatal(err)
  365. }
  366. if feed.Entries[0].Title != `http://example.org/entry` {
  367. t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title)
  368. }
  369. }
  370. func TestParseEntryWithXHTMLTitleWithoutDiv(t *testing.T) {
  371. data := `<?xml version="1.0" encoding="utf-8"?>
  372. <feed xmlns="http://www.w3.org/2005/Atom">
  373. <title>Example Feed</title>
  374. <link href="http://example.org/"/>
  375. <entry>
  376. <title type="xhtml">
  377. test
  378. </title>
  379. <link href="http://example.org/entry"/>
  380. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  381. <updated>2003-12-13T18:30:02Z</updated>
  382. </entry>
  383. </feed>`
  384. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  385. if err != nil {
  386. t.Fatal(err)
  387. }
  388. if feed.Entries[0].Title != `test` {
  389. t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title)
  390. }
  391. }
  392. func TestParseEntryWithNumericCharacterReferenceTitle(t *testing.T) {
  393. data := `<?xml version="1.0" encoding="utf-8"?>
  394. <feed xmlns="http://www.w3.org/2005/Atom">
  395. <title>Example Feed</title>
  396. <link href="http://example.org/"/>
  397. <entry>
  398. <title>&#931; &#xDF;</title>
  399. <link href="http://example.org/2003/12/13/atom03"/>
  400. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  401. <updated>2003-12-13T18:30:02Z</updated>
  402. <summary>Some text.</summary>
  403. </entry>
  404. </feed>`
  405. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  406. if err != nil {
  407. t.Fatal(err)
  408. }
  409. if feed.Entries[0].Title != "Σ ß" {
  410. t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title)
  411. }
  412. }
  413. func TestParseEntryWithDoubleEncodedEntitiesTitle(t *testing.T) {
  414. data := `<?xml version="1.0" encoding="utf-8"?>
  415. <feed xmlns="http://www.w3.org/2005/Atom">
  416. <title>Example Feed</title>
  417. <link href="http://example.org/"/>
  418. <entry>
  419. <title>&amp;#39;AT&amp;amp;T&amp;#39;</title>
  420. <link href="http://example.org/2003/12/13/atom03"/>
  421. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  422. <updated>2003-12-13T18:30:02Z</updated>
  423. <summary>Some text.</summary>
  424. </entry>
  425. </feed>`
  426. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  427. if err != nil {
  428. t.Fatal(err)
  429. }
  430. if feed.Entries[0].Title != `&#39;AT&amp;T&#39;` {
  431. t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title)
  432. }
  433. }
  434. func TestParseEntryWithXHTMLSummary(t *testing.T) {
  435. data := `<?xml version="1.0" encoding="utf-8"?>
  436. <feed xmlns="http://www.w3.org/2005/Atom">
  437. <title>Example Feed</title>
  438. <link href="http://example.org/"/>
  439. <entry>
  440. <title type="xhtml">Example</title>
  441. <link href="http://example.org/2003/12/13/atom03"/>
  442. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  443. <updated>2003-12-13T18:30:02Z</updated>
  444. <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>Test: <code>std::unique_ptr&lt;S&gt;</code></p></div></summary>
  445. </entry>
  446. </feed>`
  447. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  448. if err != nil {
  449. t.Fatal(err)
  450. }
  451. if feed.Entries[0].Content != `<p>Test: <code>std::unique_ptr&lt;S&gt;</code></p>` {
  452. t.Errorf("Incorrect entry content, got: %s", feed.Entries[1].Content)
  453. }
  454. }
  455. func TestParseEntryWithHTMLSummary(t *testing.T) {
  456. data := `<?xml version="1.0" encoding="utf-8"?>
  457. <feed xmlns="http://www.w3.org/2005/Atom">
  458. <title>Example Feed</title>
  459. <link href="http://example.org/"/>
  460. <entry>
  461. <title type="html">Example</title>
  462. <link href="http://example.org/1"/>
  463. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  464. <updated>2003-12-13T18:30:02Z</updated>
  465. <summary type="html">&lt;code&gt;std::unique_ptr&amp;lt;S&amp;gt;&lt;/code&gt;</summary>
  466. </entry>
  467. <entry>
  468. <title type="html">Example</title>
  469. <link href="http://example.org/2"/>
  470. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  471. <updated>2003-12-13T18:30:02Z</updated>
  472. <summary type="text/html">&lt;code&gt;std::unique_ptr&amp;lt;S&amp;gt;&lt;/code&gt;</summary>
  473. </entry>
  474. <entry>
  475. <title type="html">Example</title>
  476. <link href="http://example.org/3"/>
  477. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  478. <updated>2003-12-13T18:30:02Z</updated>
  479. <summary type="html"><![CDATA[<code>std::unique_ptr&lt;S&gt;</code>]]></summary>
  480. </entry>
  481. </feed>`
  482. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  483. if err != nil {
  484. t.Fatal(err)
  485. }
  486. expected := `<code>std::unique_ptr&lt;S&gt;</code>`
  487. for i := 0; i < 3; i++ {
  488. if feed.Entries[i].Content != expected {
  489. t.Errorf("Incorrect content for entry #%d, got: %q", i, feed.Entries[i].Content)
  490. }
  491. }
  492. }
  493. func TestParseEntryWithTextSummary(t *testing.T) {
  494. data := `<?xml version="1.0" encoding="utf-8"?>
  495. <feed xmlns="http://www.w3.org/2005/Atom">
  496. <title>Example Feed</title>
  497. <link href="http://example.org/"/>
  498. <entry>
  499. <title type="html">Example</title>
  500. <link href="http://example.org/a"/>
  501. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  502. <updated>2003-12-13T18:30:02Z</updated>
  503. <summary>AT&amp;T &lt;S&gt;</summary>
  504. </entry>
  505. <entry>
  506. <title type="html">Example</title>
  507. <link href="http://example.org/b"/>
  508. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  509. <updated>2003-12-13T18:30:02Z</updated>
  510. <summary type="text">AT&amp;T &lt;S&gt;</summary>
  511. </entry>
  512. <entry>
  513. <title type="html">Example</title>
  514. <link href="http://example.org/c"/>
  515. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  516. <updated>2003-12-13T18:30:02Z</updated>
  517. <summary type="text/plain">AT&amp;T &lt;S&gt;</summary>
  518. </entry>
  519. <entry>
  520. <title type="html">Example</title>
  521. <link href="http://example.org/d"/>
  522. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  523. <updated>2003-12-13T18:30:02Z</updated>
  524. <summary type="text"><![CDATA[AT&T <S>]]></summary>
  525. </entry>
  526. </feed>`
  527. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  528. if err != nil {
  529. t.Fatal(err)
  530. }
  531. expected := `AT&amp;T &lt;S&gt;`
  532. for i := 0; i < 4; i++ {
  533. if feed.Entries[i].Content != expected {
  534. t.Errorf("Incorrect content for entry #%d, got: %q", i, feed.Entries[i].Content)
  535. }
  536. }
  537. }
  538. func TestParseEntryWithTextContent(t *testing.T) {
  539. data := `<?xml version="1.0" encoding="utf-8"?>
  540. <feed xmlns="http://www.w3.org/2005/Atom">
  541. <title>Example Feed</title>
  542. <link href="http://example.org/"/>
  543. <entry>
  544. <title type="html">Example</title>
  545. <link href="http://example.org/a"/>
  546. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  547. <updated>2003-12-13T18:30:02Z</updated>
  548. <content>AT&amp;T &lt;S&gt;</content>
  549. </entry>
  550. <entry>
  551. <title type="html">Example</title>
  552. <link href="http://example.org/b"/>
  553. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  554. <updated>2003-12-13T18:30:02Z</updated>
  555. <content type="text">AT&amp;T &lt;S&gt;</content>
  556. </entry>
  557. <entry>
  558. <title type="html">Example</title>
  559. <link href="http://example.org/c"/>
  560. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  561. <updated>2003-12-13T18:30:02Z</updated>
  562. <content type="text/plain">AT&amp;T &lt;S&gt;</content>
  563. </entry>
  564. <entry>
  565. <title type="html">Example</title>
  566. <link href="http://example.org/d"/>
  567. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  568. <updated>2003-12-13T18:30:02Z</updated>
  569. <content><![CDATA[AT&T <S>]]></content>
  570. </entry>
  571. </feed>`
  572. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  573. if err != nil {
  574. t.Fatal(err)
  575. }
  576. expected := `AT&amp;T &lt;S&gt;`
  577. for i := 0; i < 4; i++ {
  578. if feed.Entries[i].Content != expected {
  579. t.Errorf("Incorrect content for entry #%d, got: %q", i, feed.Entries[i].Content)
  580. }
  581. }
  582. }
  583. func TestParseEntryWithHTMLContent(t *testing.T) {
  584. data := `<?xml version="1.0" encoding="utf-8"?>
  585. <feed xmlns="http://www.w3.org/2005/Atom">
  586. <title>Example Feed</title>
  587. <link href="http://example.org/"/>
  588. <entry>
  589. <title type="html">Example</title>
  590. <link href="http://example.org/a"/>
  591. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  592. <updated>2003-12-13T18:30:02Z</updated>
  593. <content type="html">AT&amp;amp;T bought &lt;b&gt;by SBC&lt;/b&gt;!</content>
  594. </entry>
  595. <entry>
  596. <title type="html">Example</title>
  597. <link href="http://example.org/b"/>
  598. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  599. <updated>2003-12-13T18:30:02Z</updated>
  600. <content type="text/html">AT&amp;amp;T bought &lt;b&gt;by SBC&lt;/b&gt;!</content>
  601. </entry>
  602. <entry>
  603. <title type="html">Example</title>
  604. <link href="http://example.org/c"/>
  605. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  606. <updated>2003-12-13T18:30:02Z</updated>
  607. <content type="html"><![CDATA[AT&amp;T bought <b>by SBC</b>!]]></content>
  608. </entry>
  609. </feed>`
  610. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  611. if err != nil {
  612. t.Fatal(err)
  613. }
  614. expected := `AT&amp;T bought <b>by SBC</b>!`
  615. for i := 0; i < 3; i++ {
  616. if feed.Entries[i].Content != expected {
  617. t.Errorf("Incorrect content for entry #%d, got: %q", i, feed.Entries[i].Content)
  618. }
  619. }
  620. }
  621. func TestParseEntryWithXHTMLContent(t *testing.T) {
  622. data := `<?xml version="1.0" encoding="utf-8"?>
  623. <feed xmlns="http://www.w3.org/2005/Atom">
  624. <title>Example Feed</title>
  625. <link href="http://example.org/"/>
  626. <entry>
  627. <title>Example</title>
  628. <link href="http://example.org/2003/12/13/atom03"/>
  629. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  630. <updated>2003-12-13T18:30:02Z</updated>
  631. <content type="xhtml">
  632. <div xmlns="http://www.w3.org/1999/xhtml">AT&amp;T bought <b>by SBC</b>!</div>
  633. </content>
  634. </entry>
  635. </feed>`
  636. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  637. if err != nil {
  638. t.Fatal(err)
  639. }
  640. if feed.Entries[0].Content != `AT&amp;T bought <b>by SBC</b>!` {
  641. t.Errorf("Incorrect entry content, got: %q", feed.Entries[0].Content)
  642. }
  643. }
  644. func TestParseEntryWithAuthorName(t *testing.T) {
  645. data := `<?xml version="1.0" encoding="utf-8"?>
  646. <feed xmlns="http://www.w3.org/2005/Atom">
  647. <title>Example Feed</title>
  648. <link href="http://example.org/"/>
  649. <entry>
  650. <link href="http://example.org/2003/12/13/atom03"/>
  651. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  652. <updated>2003-12-13T18:30:02Z</updated>
  653. <summary>Some text.</summary>
  654. <author>
  655. <name>Me</name>
  656. <email>me@localhost</email>
  657. </author>
  658. </entry>
  659. </feed>`
  660. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  661. if err != nil {
  662. t.Fatal(err)
  663. }
  664. if feed.Entries[0].Author != "Me" {
  665. t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author)
  666. }
  667. }
  668. func TestParseEntryWithoutAuthorName(t *testing.T) {
  669. data := `<?xml version="1.0" encoding="utf-8"?>
  670. <feed xmlns="http://www.w3.org/2005/Atom">
  671. <title>Example Feed</title>
  672. <link href="http://example.org/"/>
  673. <entry>
  674. <link href="http://example.org/2003/12/13/atom03"/>
  675. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  676. <updated>2003-12-13T18:30:02Z</updated>
  677. <summary>Some text.</summary>
  678. <author>
  679. <name/>
  680. <email>me@localhost</email>
  681. </author>
  682. </entry>
  683. </feed>`
  684. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  685. if err != nil {
  686. t.Fatal(err)
  687. }
  688. if feed.Entries[0].Author != "me@localhost" {
  689. t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author)
  690. }
  691. }
  692. func TestParseEntryWithMultipleAuthors(t *testing.T) {
  693. data := `<?xml version="1.0" encoding="utf-8"?>
  694. <feed xmlns="http://www.w3.org/2005/Atom">
  695. <title>Example Feed</title>
  696. <link href="http://example.org/"/>
  697. <entry>
  698. <link href="http://example.org/2003/12/13/atom03"/>
  699. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  700. <updated>2003-12-13T18:30:02Z</updated>
  701. <summary>Some text.</summary>
  702. <author>
  703. <name>Alice</name>
  704. </author>
  705. <author>
  706. <name>Bob</name>
  707. </author>
  708. </entry>
  709. </feed>`
  710. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  711. if err != nil {
  712. t.Fatal(err)
  713. }
  714. if feed.Entries[0].Author != "Alice, Bob" {
  715. t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author)
  716. }
  717. }
  718. func TestParseEntryWithoutAuthor(t *testing.T) {
  719. data := `<?xml version="1.0" encoding="utf-8"?>
  720. <feed xmlns="http://www.w3.org/2005/Atom">
  721. <title>Example Feed</title>
  722. <link href="http://example.org/"/>
  723. <author>
  724. <name>John Doe</name>
  725. </author>
  726. <entry>
  727. <link href="http://example.org/2003/12/13/atom03"/>
  728. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  729. <updated>2003-12-13T18:30:02Z</updated>
  730. <summary>Some text.</summary>
  731. </entry>
  732. </feed>`
  733. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  734. if err != nil {
  735. t.Fatal(err)
  736. }
  737. if feed.Entries[0].Author != "John Doe" {
  738. t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author)
  739. }
  740. }
  741. func TestParseFeedWithMultipleAuthors(t *testing.T) {
  742. data := `<?xml version="1.0" encoding="utf-8"?>
  743. <feed xmlns="http://www.w3.org/2005/Atom">
  744. <title>Example Feed</title>
  745. <link href="http://example.org/"/>
  746. <author>
  747. <name>Alice</name>
  748. </author>
  749. <author>
  750. <name>Bob</name>
  751. </author>
  752. <entry>
  753. <link href="http://example.org/2003/12/13/atom03"/>
  754. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  755. <updated>2003-12-13T18:30:02Z</updated>
  756. <summary>Some text.</summary>
  757. </entry>
  758. </feed>`
  759. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  760. if err != nil {
  761. t.Fatal(err)
  762. }
  763. if feed.Entries[0].Author != "Alice, Bob" {
  764. t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author)
  765. }
  766. }
  767. func TestParseFeedWithoutAuthor(t *testing.T) {
  768. data := `<?xml version="1.0" encoding="utf-8"?>
  769. <feed xmlns="http://www.w3.org/2005/Atom">
  770. <title>Example Feed</title>
  771. <link href="http://example.org/"/>
  772. <entry>
  773. <link href="http://example.org/2003/12/13/atom03"/>
  774. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  775. <updated>2003-12-13T18:30:02Z</updated>
  776. <summary>Some text.</summary>
  777. </entry>
  778. </feed>`
  779. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  780. if err != nil {
  781. t.Fatal(err)
  782. }
  783. if feed.Entries[0].Author != "" {
  784. t.Errorf("Incorrect entry author, got: %q", feed.Entries[0].Author)
  785. }
  786. }
  787. func TestParseEntryWithEnclosures(t *testing.T) {
  788. data := `<?xml version="1.0" encoding="utf-8"?>
  789. <feed xmlns="http://www.w3.org/2005/Atom">
  790. <id>http://www.example.org/myfeed</id>
  791. <title>My Podcast Feed</title>
  792. <updated>2005-07-15T12:00:00Z</updated>
  793. <author>
  794. <name>John Doe</name>
  795. </author>
  796. <link href="http://example.org" />
  797. <link rel="self" href="http://example.org/myfeed" />
  798. <entry>
  799. <id>http://www.example.org/entries/1</id>
  800. <title>Atom 1.0</title>
  801. <updated>2005-07-15T12:00:00Z</updated>
  802. <link href="http://www.example.org/entries/1" />
  803. <summary>An overview of Atom 1.0</summary>
  804. <link rel="enclosure"
  805. type="audio/mpeg"
  806. title="MP3"
  807. href="http://www.example.org/myaudiofile.mp3"
  808. length="1234" />
  809. <link rel="enclosure"
  810. type="application/x-bittorrent"
  811. title="BitTorrent"
  812. href="http://www.example.org/myaudiofile.torrent"
  813. length="4567" />
  814. <content type="xhtml">
  815. <div xmlns="http://www.w3.org/1999/xhtml">
  816. <h1>Show Notes</h1>
  817. <ul>
  818. <li>00:01:00 -- Introduction</li>
  819. <li>00:15:00 -- Talking about Atom 1.0</li>
  820. <li>00:30:00 -- Wrapping up</li>
  821. </ul>
  822. </div>
  823. </content>
  824. </entry>
  825. </feed>`
  826. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  827. if err != nil {
  828. t.Fatal(err)
  829. }
  830. if len(feed.Entries) != 1 {
  831. t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries))
  832. }
  833. if feed.Entries[0].URL != "http://www.example.org/entries/1" {
  834. t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL)
  835. }
  836. if len(feed.Entries[0].Enclosures) != 2 {
  837. t.Fatalf("Incorrect number of enclosures, got: %d", len(feed.Entries[0].Enclosures))
  838. }
  839. expectedResults := []struct {
  840. url string
  841. mimeType string
  842. size int64
  843. }{
  844. {"http://www.example.org/myaudiofile.mp3", "audio/mpeg", 1234},
  845. {"http://www.example.org/myaudiofile.torrent", "application/x-bittorrent", 4567},
  846. }
  847. for index, enclosure := range feed.Entries[0].Enclosures {
  848. if expectedResults[index].url != enclosure.URL {
  849. t.Errorf(`Unexpected enclosure URL, got %q instead of %q`, enclosure.URL, expectedResults[index].url)
  850. }
  851. if expectedResults[index].mimeType != enclosure.MimeType {
  852. t.Errorf(`Unexpected enclosure type, got %q instead of %q`, enclosure.MimeType, expectedResults[index].mimeType)
  853. }
  854. if expectedResults[index].size != enclosure.Size {
  855. t.Errorf(`Unexpected enclosure size, got %d instead of %d`, enclosure.Size, expectedResults[index].size)
  856. }
  857. }
  858. }
  859. func TestParseEntryWithoutEnclosureURL(t *testing.T) {
  860. data := `<?xml version="1.0" encoding="utf-8"?>
  861. <feed xmlns="http://www.w3.org/2005/Atom">
  862. <id>http://www.example.org/myfeed</id>
  863. <title>My Podcast Feed</title>
  864. <updated>2005-07-15T12:00:00Z</updated>
  865. <link href="http://example.org" />
  866. <link rel="self" href="http://example.org/myfeed" />
  867. <entry>
  868. <id>http://www.example.org/entries/1</id>
  869. <title>Atom 1.0</title>
  870. <updated>2005-07-15T12:00:00Z</updated>
  871. <link href="http://www.example.org/entries/1" />
  872. <summary>An overview of Atom 1.0</summary>
  873. <link rel="enclosure" href="" length="0" />
  874. <content type="xhtml">Test</content>
  875. </entry>
  876. </feed>`
  877. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  878. if err != nil {
  879. t.Fatal(err)
  880. }
  881. if len(feed.Entries) != 1 {
  882. t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries))
  883. }
  884. if feed.Entries[0].URL != "http://www.example.org/entries/1" {
  885. t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL)
  886. }
  887. if len(feed.Entries[0].Enclosures) != 0 {
  888. t.Fatalf("Incorrect number of enclosures, got: %d", len(feed.Entries[0].Enclosures))
  889. }
  890. }
  891. func TestParseEntryWithPublished(t *testing.T) {
  892. data := `<?xml version="1.0" encoding="utf-8"?>
  893. <feed xmlns="http://www.w3.org/2005/Atom">
  894. <title>Example Feed</title>
  895. <link href="http://example.org/"/>
  896. <entry>
  897. <link href="http://example.org/2003/12/13/atom03"/>
  898. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  899. <published>2003-12-13T18:30:02Z</published>
  900. <summary>Some text.</summary>
  901. </entry>
  902. </feed>`
  903. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  904. if err != nil {
  905. t.Fatal(err)
  906. }
  907. if !feed.Entries[0].Date.Equal(time.Date(2003, time.December, 13, 18, 30, 2, 0, time.UTC)) {
  908. t.Errorf("Incorrect entry date, got: %v", feed.Entries[0].Date)
  909. }
  910. }
  911. func TestParseEntryWithPublishedAndUpdated(t *testing.T) {
  912. data := `<?xml version="1.0" encoding="utf-8"?>
  913. <feed xmlns="http://www.w3.org/2005/Atom">
  914. <title>Example Feed</title>
  915. <link href="http://example.org/"/>
  916. <entry>
  917. <link href="http://example.org/2003/12/13/atom03"/>
  918. <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  919. <published>2002-11-12T18:30:02Z</published>
  920. <updated>2003-12-13T18:30:02Z</updated>
  921. <summary>Some text.</summary>
  922. </entry>
  923. </feed>`
  924. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  925. if err != nil {
  926. t.Fatal(err)
  927. }
  928. if !feed.Entries[0].Date.Equal(time.Date(2002, time.November, 12, 18, 30, 2, 0, time.UTC)) {
  929. t.Errorf("Incorrect entry date, got: %v", feed.Entries[0].Date)
  930. }
  931. }
  932. func TestParseInvalidXml(t *testing.T) {
  933. data := `garbage`
  934. _, err := Parse("https://example.org/", bytes.NewBufferString(data))
  935. if err == nil {
  936. t.Error("Parse should returns an error")
  937. }
  938. }
  939. func TestParseTitleWithSingleQuote(t *testing.T) {
  940. data := `
  941. <?xml version="1.0" encoding="utf-8"?>
  942. <feed xmlns="http://www.w3.org/2005/Atom">
  943. <title>' or ’</title>
  944. <link href="http://example.org/"/>
  945. </feed>
  946. `
  947. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  948. if err != nil {
  949. t.Fatal(err)
  950. }
  951. if feed.Title != "' or ’" {
  952. t.Errorf(`Incorrect title, got: %q`, feed.Title)
  953. }
  954. }
  955. func TestParseTitleWithEncodedSingleQuote(t *testing.T) {
  956. data := `
  957. <?xml version="1.0" encoding="utf-8"?>
  958. <feed xmlns="http://www.w3.org/2005/Atom">
  959. <title type="html">Test&#39;s Blog</title>
  960. <link href="http://example.org/"/>
  961. </feed>
  962. `
  963. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  964. if err != nil {
  965. t.Fatal(err)
  966. }
  967. if feed.Title != "Test's Blog" {
  968. t.Errorf(`Incorrect title, got: %q`, feed.Title)
  969. }
  970. }
  971. func TestParseTitleWithSingleQuoteAndHTMLType(t *testing.T) {
  972. data := `
  973. <?xml version="1.0" encoding="utf-8"?>
  974. <feed xmlns="http://www.w3.org/2005/Atom">
  975. <title type="html">O’Hara</title>
  976. <link href="http://example.org/"/>
  977. </feed>
  978. `
  979. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  980. if err != nil {
  981. t.Fatal(err)
  982. }
  983. if feed.Title != "O’Hara" {
  984. t.Errorf(`Incorrect title, got: %q`, feed.Title)
  985. }
  986. }
  987. func TestParseWithHTMLEntity(t *testing.T) {
  988. data := `
  989. <?xml version="1.0" encoding="utf-8"?>
  990. <feed xmlns="http://www.w3.org/2005/Atom">
  991. <title>Example &nbsp; Feed</title>
  992. <link href="http://example.org/"/>
  993. </feed>
  994. `
  995. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  996. if err != nil {
  997. t.Fatal(err)
  998. }
  999. if feed.Title != "Example \u00a0 Feed" {
  1000. t.Errorf(`Incorrect title, got: %q`, feed.Title)
  1001. }
  1002. }
  1003. func TestParseWithInvalidCharacterEntity(t *testing.T) {
  1004. data := `
  1005. <?xml version="1.0" encoding="utf-8"?>
  1006. <feed xmlns="http://www.w3.org/2005/Atom">
  1007. <title>Example Feed</title>
  1008. <link href="http://example.org/a&b"/>
  1009. </feed>
  1010. `
  1011. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  1012. if err != nil {
  1013. t.Fatal(err)
  1014. }
  1015. if feed.SiteURL != "http://example.org/a&b" {
  1016. t.Errorf(`Incorrect URL, got: %q`, feed.SiteURL)
  1017. }
  1018. }
  1019. func TestParseMediaGroup(t *testing.T) {
  1020. data := `<?xml version="1.0" encoding="utf-8"?>
  1021. <feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
  1022. <id>http://www.example.org/myfeed</id>
  1023. <title>My Video Feed</title>
  1024. <updated>2005-07-15T12:00:00Z</updated>
  1025. <link href="http://example.org" />
  1026. <link rel="self" href="http://example.org/myfeed" />
  1027. <entry>
  1028. <id>http://www.example.org/entries/1</id>
  1029. <title>Some Video</title>
  1030. <updated>2005-07-15T12:00:00Z</updated>
  1031. <link href="http://www.example.org/entries/1" />
  1032. <media:group>
  1033. <media:title>Another title</media:title>
  1034. <media:content url="https://www.youtube.com/v/abcd" type="application/x-shockwave-flash" width="640" height="390"/>
  1035. <media:thumbnail url="https://example.org/thumbnail.jpg" width="480" height="360"/>
  1036. <media:description>Some description
  1037. A website: http://example.org/</media:description>
  1038. </media:group>
  1039. </entry>
  1040. </feed>`
  1041. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  1042. if err != nil {
  1043. t.Fatal(err)
  1044. }
  1045. if len(feed.Entries) != 1 {
  1046. t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries))
  1047. }
  1048. if feed.Entries[0].URL != "http://www.example.org/entries/1" {
  1049. t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL)
  1050. }
  1051. if feed.Entries[0].Content != `Some description<br>A website: <a href="http://example.org/">http://example.org/</a>` {
  1052. t.Errorf("Incorrect entry content, got: %q", feed.Entries[0].Content)
  1053. }
  1054. if len(feed.Entries[0].Enclosures) != 2 {
  1055. t.Fatalf("Incorrect number of enclosures, got: %d", len(feed.Entries[0].Enclosures))
  1056. }
  1057. expectedResults := []struct {
  1058. url string
  1059. mimeType string
  1060. size int64
  1061. }{
  1062. {"https://example.org/thumbnail.jpg", "image/*", 0},
  1063. {"https://www.youtube.com/v/abcd", "application/x-shockwave-flash", 0},
  1064. }
  1065. for index, enclosure := range feed.Entries[0].Enclosures {
  1066. if expectedResults[index].url != enclosure.URL {
  1067. t.Errorf(`Unexpected enclosure URL, got %q instead of %q`, enclosure.URL, expectedResults[index].url)
  1068. }
  1069. if expectedResults[index].mimeType != enclosure.MimeType {
  1070. t.Errorf(`Unexpected enclosure type, got %q instead of %q`, enclosure.MimeType, expectedResults[index].mimeType)
  1071. }
  1072. if expectedResults[index].size != enclosure.Size {
  1073. t.Errorf(`Unexpected enclosure size, got %d instead of %d`, enclosure.Size, expectedResults[index].size)
  1074. }
  1075. }
  1076. }
  1077. func TestParseMediaElements(t *testing.T) {
  1078. data := `<?xml version="1.0" encoding="utf-8"?>
  1079. <feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
  1080. <id>http://www.example.org/myfeed</id>
  1081. <title>My Video Feed</title>
  1082. <updated>2005-07-15T12:00:00Z</updated>
  1083. <link href="http://example.org" />
  1084. <link rel="self" href="http://example.org/myfeed" />
  1085. <entry>
  1086. <id>http://www.example.org/entries/1</id>
  1087. <title>Some Video</title>
  1088. <updated>2005-07-15T12:00:00Z</updated>
  1089. <link href="http://www.example.org/entries/1" />
  1090. <media:title>Another title</media:title>
  1091. <media:content url="https://www.youtube.com/v/abcd" type="application/x-shockwave-flash" width="640" height="390"/>
  1092. <media:thumbnail url="https://example.org/thumbnail.jpg" width="480" height="360"/>
  1093. <media:description>Some description
  1094. A website: http://example.org/</media:description>
  1095. </entry>
  1096. </feed>`
  1097. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  1098. if err != nil {
  1099. t.Fatal(err)
  1100. }
  1101. if len(feed.Entries) != 1 {
  1102. t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries))
  1103. }
  1104. if feed.Entries[0].URL != "http://www.example.org/entries/1" {
  1105. t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL)
  1106. }
  1107. if feed.Entries[0].Content != `Some description<br>A website: <a href="http://example.org/">http://example.org/</a>` {
  1108. t.Errorf("Incorrect entry content, got: %q", feed.Entries[0].Content)
  1109. }
  1110. if len(feed.Entries[0].Enclosures) != 2 {
  1111. t.Fatalf("Incorrect number of enclosures, got: %d", len(feed.Entries[0].Enclosures))
  1112. }
  1113. expectedResults := []struct {
  1114. url string
  1115. mimeType string
  1116. size int64
  1117. }{
  1118. {"https://example.org/thumbnail.jpg", "image/*", 0},
  1119. {"https://www.youtube.com/v/abcd", "application/x-shockwave-flash", 0},
  1120. }
  1121. for index, enclosure := range feed.Entries[0].Enclosures {
  1122. if expectedResults[index].url != enclosure.URL {
  1123. t.Errorf(`Unexpected enclosure URL, got %q instead of %q`, enclosure.URL, expectedResults[index].url)
  1124. }
  1125. if expectedResults[index].mimeType != enclosure.MimeType {
  1126. t.Errorf(`Unexpected enclosure type, got %q instead of %q`, enclosure.MimeType, expectedResults[index].mimeType)
  1127. }
  1128. if expectedResults[index].size != enclosure.Size {
  1129. t.Errorf(`Unexpected enclosure size, got %d instead of %d`, enclosure.Size, expectedResults[index].size)
  1130. }
  1131. }
  1132. }
  1133. func TestParseRepliesLinkRelationWithHTMLType(t *testing.T) {
  1134. data := `<?xml version="1.0" encoding="utf-8"?>
  1135. <feed xmlns="http://www.w3.org/2005/Atom"
  1136. xmlns:thr="http://purl.org/syndication/thread/1.0">
  1137. <id>http://www.example.org/myfeed</id>
  1138. <title>My Example Feed</title>
  1139. <updated>2005-07-28T12:00:00Z</updated>
  1140. <link href="http://www.example.org/myfeed" />
  1141. <author><name>James</name></author>
  1142. <entry>
  1143. <id>tag:entries.com,2005:1</id>
  1144. <title>My original entry</title>
  1145. <updated>2006-03-01T12:12:12Z</updated>
  1146. <link href="http://www.example.org/entries/1" />
  1147. <link rel="replies"
  1148. type="application/atom+xml"
  1149. href="http://www.example.org/mycommentsfeed.xml"
  1150. thr:count="10" thr:updated="2005-07-28T12:10:00Z" />
  1151. <link rel="replies"
  1152. type="text/html"
  1153. href="http://www.example.org/comments.html"
  1154. thr:count="10" thr:updated="2005-07-28T12:10:00Z" />
  1155. <summary>This is my original entry</summary>
  1156. </entry>
  1157. </feed>`
  1158. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  1159. if err != nil {
  1160. t.Fatal(err)
  1161. }
  1162. if len(feed.Entries) != 1 {
  1163. t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries))
  1164. }
  1165. if feed.Entries[0].URL != "http://www.example.org/entries/1" {
  1166. t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL)
  1167. }
  1168. if feed.Entries[0].CommentsURL != "http://www.example.org/comments.html" {
  1169. t.Errorf("Incorrect entry comments URL, got: %s", feed.Entries[0].CommentsURL)
  1170. }
  1171. }
  1172. func TestParseRepliesLinkRelationWithXHTMLType(t *testing.T) {
  1173. data := `<?xml version="1.0" encoding="utf-8"?>
  1174. <feed xmlns="http://www.w3.org/2005/Atom"
  1175. xmlns:thr="http://purl.org/syndication/thread/1.0">
  1176. <id>http://www.example.org/myfeed</id>
  1177. <title>My Example Feed</title>
  1178. <updated>2005-07-28T12:00:00Z</updated>
  1179. <link href="http://www.example.org/myfeed" />
  1180. <author><name>James</name></author>
  1181. <entry>
  1182. <id>tag:entries.com,2005:1</id>
  1183. <title>My original entry</title>
  1184. <updated>2006-03-01T12:12:12Z</updated>
  1185. <link href="http://www.example.org/entries/1" />
  1186. <link rel="replies"
  1187. type="application/atom+xml"
  1188. href="http://www.example.org/mycommentsfeed.xml"
  1189. thr:count="10" thr:updated="2005-07-28T12:10:00Z" />
  1190. <link rel="replies"
  1191. type="application/xhtml+xml"
  1192. href="http://www.example.org/comments.xhtml"
  1193. thr:count="10" thr:updated="2005-07-28T12:10:00Z" />
  1194. <summary>This is my original entry</summary>
  1195. </entry>
  1196. </feed>`
  1197. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  1198. if err != nil {
  1199. t.Fatal(err)
  1200. }
  1201. if len(feed.Entries) != 1 {
  1202. t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries))
  1203. }
  1204. if feed.Entries[0].URL != "http://www.example.org/entries/1" {
  1205. t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL)
  1206. }
  1207. if feed.Entries[0].CommentsURL != "http://www.example.org/comments.xhtml" {
  1208. t.Errorf("Incorrect entry comments URL, got: %s", feed.Entries[0].CommentsURL)
  1209. }
  1210. }
  1211. func TestParseRepliesLinkRelationWithNoType(t *testing.T) {
  1212. data := `<?xml version="1.0" encoding="utf-8"?>
  1213. <feed xmlns="http://www.w3.org/2005/Atom"
  1214. xmlns:thr="http://purl.org/syndication/thread/1.0">
  1215. <id>http://www.example.org/myfeed</id>
  1216. <title>My Example Feed</title>
  1217. <updated>2005-07-28T12:00:00Z</updated>
  1218. <link href="http://www.example.org/myfeed" />
  1219. <author><name>James</name></author>
  1220. <entry>
  1221. <id>tag:entries.com,2005:1</id>
  1222. <title>My original entry</title>
  1223. <updated>2006-03-01T12:12:12Z</updated>
  1224. <link href="http://www.example.org/entries/1" />
  1225. <link rel="replies"
  1226. href="http://www.example.org/mycommentsfeed.xml"
  1227. thr:count="10" thr:updated="2005-07-28T12:10:00Z" />
  1228. <summary>This is my original entry</summary>
  1229. </entry>
  1230. </feed>`
  1231. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  1232. if err != nil {
  1233. t.Fatal(err)
  1234. }
  1235. if len(feed.Entries) != 1 {
  1236. t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries))
  1237. }
  1238. if feed.Entries[0].URL != "http://www.example.org/entries/1" {
  1239. t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL)
  1240. }
  1241. if feed.Entries[0].CommentsURL != "" {
  1242. t.Errorf("Incorrect entry comments URL, got: %s", feed.Entries[0].CommentsURL)
  1243. }
  1244. }
  1245. func TestAbsoluteCommentsURL(t *testing.T) {
  1246. data := `<?xml version="1.0" encoding="utf-8"?>
  1247. <feed xmlns="http://www.w3.org/2005/Atom"
  1248. xmlns:thr="http://purl.org/syndication/thread/1.0">
  1249. <id>http://www.example.org/myfeed</id>
  1250. <title>My Example Feed</title>
  1251. <updated>2005-07-28T12:00:00Z</updated>
  1252. <link href="http://www.example.org/myfeed" />
  1253. <author><name>James</name></author>
  1254. <entry>
  1255. <id>tag:entries.com,2005:1</id>
  1256. <title>My original entry</title>
  1257. <updated>2006-03-01T12:12:12Z</updated>
  1258. <link href="http://www.example.org/entries/1" />
  1259. <link rel="replies"
  1260. type="text/html"
  1261. href="invalid url"
  1262. thr:count="10" thr:updated="2005-07-28T12:10:00Z" />
  1263. <summary>This is my original entry</summary>
  1264. </entry>
  1265. </feed>`
  1266. feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
  1267. if err != nil {
  1268. t.Fatal(err)
  1269. }
  1270. if len(feed.Entries) != 1 {
  1271. t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries))
  1272. }
  1273. if feed.Entries[0].URL != "http://www.example.org/entries/1" {
  1274. t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL)
  1275. }
  1276. if feed.Entries[0].CommentsURL != "" {
  1277. t.Errorf("Incorrect entry comments URL, got: %s", feed.Entries[0].CommentsURL)
  1278. }
  1279. }