finder_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package subscription
  4. import (
  5. "strings"
  6. "testing"
  7. )
  8. func TestFindYoutubePlaylistFeed(t *testing.T) {
  9. scenarios := map[string]string{
  10. "https://www.youtube.com/playlist?list=PLOOwEPgFWm_NHcQd9aCi5JXWASHO_n5uR": "https://www.youtube.com/feeds/videos.xml?playlist_id=PLOOwEPgFWm_NHcQd9aCi5JXWASHO_n5uR",
  11. "https://www.youtube.com/playlist?list=PLOOwEPgFWm_N42HlCLhqyJ0ZBWr5K1QDM": "https://www.youtube.com/feeds/videos.xml?playlist_id=PLOOwEPgFWm_N42HlCLhqyJ0ZBWr5K1QDM",
  12. }
  13. for websiteURL, expectedFeedURL := range scenarios {
  14. subscriptions, localizedError := NewSubscriptionFinder(nil).FindSubscriptionsFromYouTubePlaylistPage(websiteURL)
  15. if localizedError != nil {
  16. t.Fatalf(`Parsing a correctly formatted YouTube playlist page should not return any error: %v`, localizedError)
  17. }
  18. if len(subscriptions) != 1 {
  19. t.Fatal(`Incorrect number of subscriptions returned`)
  20. }
  21. if subscriptions[0].URL != expectedFeedURL {
  22. t.Errorf(`Unexpected Feed, got %s, instead of %s`, subscriptions[0].URL, expectedFeedURL)
  23. }
  24. }
  25. }
  26. func TestFindYoutubeChannelFeed(t *testing.T) {
  27. scenarios := map[string]string{
  28. "https://www.youtube.com/channel/UC-Qj80avWItNRjkZ41rzHyw": "https://www.youtube.com/feeds/videos.xml?channel_id=UC-Qj80avWItNRjkZ41rzHyw",
  29. }
  30. for websiteURL, expectedFeedURL := range scenarios {
  31. subscriptions, localizedError := NewSubscriptionFinder(nil).FindSubscriptionsFromYouTubeChannelPage(websiteURL)
  32. if localizedError != nil {
  33. t.Fatalf(`Parsing a correctly formatted YouTube channel page should not return any error: %v`, localizedError)
  34. }
  35. if len(subscriptions) != 1 {
  36. t.Fatal(`Incorrect number of subscriptions returned`)
  37. }
  38. if subscriptions[0].URL != expectedFeedURL {
  39. t.Errorf(`Unexpected Feed, got %s, instead of %s`, subscriptions[0].URL, expectedFeedURL)
  40. }
  41. }
  42. }
  43. func TestParseWebPageWithRssFeed(t *testing.T) {
  44. htmlPage := `
  45. <!doctype html>
  46. <html>
  47. <head>
  48. <link href="http://example.org/rss" rel="alternate" type="application/rss+xml" title="Some Title">
  49. </head>
  50. <body>
  51. </body>
  52. </html>`
  53. subscriptions, err := NewSubscriptionFinder(nil).FindSubscriptionsFromWebPage("http://example.org/", "text/html", strings.NewReader(htmlPage))
  54. if err != nil {
  55. t.Fatalf(`Parsing a correctly formatted HTML page should not return any error: %v`, err)
  56. }
  57. if len(subscriptions) != 1 {
  58. t.Fatal(`Incorrect number of subscriptions returned`)
  59. }
  60. if subscriptions[0].Title != "Some Title" {
  61. t.Errorf(`Incorrect subscription title: %q`, subscriptions[0].Title)
  62. }
  63. if subscriptions[0].URL != "http://example.org/rss" {
  64. t.Errorf(`Incorrect subscription URL: %q`, subscriptions[0].URL)
  65. }
  66. if subscriptions[0].Type != "rss" {
  67. t.Errorf(`Incorrect subscription type: %q`, subscriptions[0].Type)
  68. }
  69. }
  70. func TestParseWebPageWithAtomFeed(t *testing.T) {
  71. htmlPage := `
  72. <!doctype html>
  73. <html>
  74. <head>
  75. <link href="http://example.org/atom.xml" rel="alternate" type="application/atom+xml" title="Some Title">
  76. </head>
  77. <body>
  78. </body>
  79. </html>`
  80. subscriptions, err := NewSubscriptionFinder(nil).FindSubscriptionsFromWebPage("http://example.org/", "text/html", strings.NewReader(htmlPage))
  81. if err != nil {
  82. t.Fatalf(`Parsing a correctly formatted HTML page should not return any error: %v`, err)
  83. }
  84. if len(subscriptions) != 1 {
  85. t.Fatal(`Incorrect number of subscriptions returned`)
  86. }
  87. if subscriptions[0].Title != "Some Title" {
  88. t.Errorf(`Incorrect subscription title: %q`, subscriptions[0].Title)
  89. }
  90. if subscriptions[0].URL != "http://example.org/atom.xml" {
  91. t.Errorf(`Incorrect subscription URL: %q`, subscriptions[0].URL)
  92. }
  93. if subscriptions[0].Type != "atom" {
  94. t.Errorf(`Incorrect subscription type: %q`, subscriptions[0].Type)
  95. }
  96. }
  97. func TestParseWebPageWithJSONFeed(t *testing.T) {
  98. htmlPage := `
  99. <!doctype html>
  100. <html>
  101. <head>
  102. <link href="http://example.org/feed.json" rel="alternate" type="application/feed+json" title="Some Title">
  103. </head>
  104. <body>
  105. </body>
  106. </html>`
  107. subscriptions, err := NewSubscriptionFinder(nil).FindSubscriptionsFromWebPage("http://example.org/", "text/html", strings.NewReader(htmlPage))
  108. if err != nil {
  109. t.Fatalf(`Parsing a correctly formatted HTML page should not return any error: %v`, err)
  110. }
  111. if len(subscriptions) != 1 {
  112. t.Fatal(`Incorrect number of subscriptions returned`)
  113. }
  114. if subscriptions[0].Title != "Some Title" {
  115. t.Errorf(`Incorrect subscription title: %q`, subscriptions[0].Title)
  116. }
  117. if subscriptions[0].URL != "http://example.org/feed.json" {
  118. t.Errorf(`Incorrect subscription URL: %q`, subscriptions[0].URL)
  119. }
  120. if subscriptions[0].Type != "json" {
  121. t.Errorf(`Incorrect subscription type: %q`, subscriptions[0].Type)
  122. }
  123. }
  124. func TestParseWebPageWithOldJSONFeedMimeType(t *testing.T) {
  125. htmlPage := `
  126. <!doctype html>
  127. <html>
  128. <head>
  129. <link href="http://example.org/feed.json" rel="alternate" type="application/json" title="Some Title">
  130. </head>
  131. <body>
  132. </body>
  133. </html>`
  134. subscriptions, err := NewSubscriptionFinder(nil).FindSubscriptionsFromWebPage("http://example.org/", "text/html", strings.NewReader(htmlPage))
  135. if err != nil {
  136. t.Fatalf(`Parsing a correctly formatted HTML page should not return any error: %v`, err)
  137. }
  138. if len(subscriptions) != 1 {
  139. t.Fatal(`Incorrect number of subscriptions returned`)
  140. }
  141. if subscriptions[0].Title != "Some Title" {
  142. t.Errorf(`Incorrect subscription title: %q`, subscriptions[0].Title)
  143. }
  144. if subscriptions[0].URL != "http://example.org/feed.json" {
  145. t.Errorf(`Incorrect subscription URL: %q`, subscriptions[0].URL)
  146. }
  147. if subscriptions[0].Type != "json" {
  148. t.Errorf(`Incorrect subscription type: %q`, subscriptions[0].Type)
  149. }
  150. }
  151. func TestParseWebPageWithRelativeFeedURL(t *testing.T) {
  152. htmlPage := `
  153. <!doctype html>
  154. <html>
  155. <head>
  156. <link href="/feed.json" rel="alternate" type="application/feed+json" title="Some Title">
  157. </head>
  158. <body>
  159. </body>
  160. </html>`
  161. subscriptions, err := NewSubscriptionFinder(nil).FindSubscriptionsFromWebPage("http://example.org/", "text/html", strings.NewReader(htmlPage))
  162. if err != nil {
  163. t.Fatalf(`Parsing a correctly formatted HTML page should not return any error: %v`, err)
  164. }
  165. if len(subscriptions) != 1 {
  166. t.Fatal(`Incorrect number of subscriptions returned`)
  167. }
  168. if subscriptions[0].Title != "Some Title" {
  169. t.Errorf(`Incorrect subscription title: %q`, subscriptions[0].Title)
  170. }
  171. if subscriptions[0].URL != "http://example.org/feed.json" {
  172. t.Errorf(`Incorrect subscription URL: %q`, subscriptions[0].URL)
  173. }
  174. if subscriptions[0].Type != "json" {
  175. t.Errorf(`Incorrect subscription type: %q`, subscriptions[0].Type)
  176. }
  177. }
  178. func TestParseWebPageWithEmptyTitle(t *testing.T) {
  179. htmlPage := `
  180. <!doctype html>
  181. <html>
  182. <head>
  183. <link href="/feed.json" rel="alternate" type="application/feed+json">
  184. </head>
  185. <body>
  186. </body>
  187. </html>`
  188. subscriptions, err := NewSubscriptionFinder(nil).FindSubscriptionsFromWebPage("http://example.org/", "text/html", strings.NewReader(htmlPage))
  189. if err != nil {
  190. t.Fatalf(`Parsing a correctly formatted HTML page should not return any error: %v`, err)
  191. }
  192. if len(subscriptions) != 1 {
  193. t.Fatal(`Incorrect number of subscriptions returned`)
  194. }
  195. if subscriptions[0].Title != "http://example.org/feed.json" {
  196. t.Errorf(`Incorrect subscription title: %q`, subscriptions[0].Title)
  197. }
  198. if subscriptions[0].URL != "http://example.org/feed.json" {
  199. t.Errorf(`Incorrect subscription URL: %q`, subscriptions[0].URL)
  200. }
  201. if subscriptions[0].Type != "json" {
  202. t.Errorf(`Incorrect subscription type: %q`, subscriptions[0].Type)
  203. }
  204. }
  205. func TestParseWebPageWithMultipleFeeds(t *testing.T) {
  206. htmlPage := `
  207. <!doctype html>
  208. <html>
  209. <head>
  210. <link href="http://example.org/atom.xml" rel="alternate" type="application/atom+xml" title="Atom Feed">
  211. <link href="http://example.org/feed.json" rel="alternate" type="application/feed+json" title="JSON Feed">
  212. </head>
  213. <body>
  214. </body>
  215. </html>`
  216. subscriptions, err := NewSubscriptionFinder(nil).FindSubscriptionsFromWebPage("http://example.org/", "text/html", strings.NewReader(htmlPage))
  217. if err != nil {
  218. t.Fatalf(`Parsing a correctly formatted HTML page should not return any error: %v`, err)
  219. }
  220. if len(subscriptions) != 2 {
  221. t.Fatal(`Incorrect number of subscriptions returned`)
  222. }
  223. }
  224. func TestParseWebPageWithDuplicatedFeeds(t *testing.T) {
  225. htmlPage := `
  226. <!doctype html>
  227. <html>
  228. <head>
  229. <link href="http://example.org/feed.xml" rel="alternate" type="application/rss+xml" title="Feed A">
  230. <link href="http://example.org/feed.xml" rel="alternate" type="application/rss+xml" title="Feed B">
  231. </head>
  232. <body>
  233. </body>
  234. </html>`
  235. subscriptions, err := NewSubscriptionFinder(nil).FindSubscriptionsFromWebPage("http://example.org/", "text/html", strings.NewReader(htmlPage))
  236. if err != nil {
  237. t.Fatalf(`Parsing a correctly formatted HTML page should not return any error: %v`, err)
  238. }
  239. if len(subscriptions) != 1 {
  240. t.Fatal(`Incorrect number of subscriptions returned`)
  241. }
  242. if subscriptions[0].Title != "Feed A" {
  243. t.Errorf(`Incorrect subscription title: %q`, subscriptions[0].Title)
  244. }
  245. if subscriptions[0].URL != "http://example.org/feed.xml" {
  246. t.Errorf(`Incorrect subscription URL: %q`, subscriptions[0].URL)
  247. }
  248. if subscriptions[0].Type != "rss" {
  249. t.Errorf(`Incorrect subscription type: %q`, subscriptions[0].Type)
  250. }
  251. }
  252. func TestParseWebPageWithEmptyFeedURL(t *testing.T) {
  253. htmlPage := `
  254. <!doctype html>
  255. <html>
  256. <head>
  257. <link href rel="alternate" type="application/feed+json" title="Some Title">
  258. </head>
  259. <body>
  260. </body>
  261. </html>`
  262. subscriptions, err := NewSubscriptionFinder(nil).FindSubscriptionsFromWebPage("http://example.org/", "text/html", strings.NewReader(htmlPage))
  263. if err != nil {
  264. t.Fatalf(`Parsing a correctly formatted HTML page should not return any error: %v`, err)
  265. }
  266. if len(subscriptions) != 0 {
  267. t.Fatal(`Incorrect number of subscriptions returned`)
  268. }
  269. }
  270. func TestParseWebPageWithNoHref(t *testing.T) {
  271. htmlPage := `
  272. <!doctype html>
  273. <html>
  274. <head>
  275. <link rel="alternate" type="application/feed+json" title="Some Title">
  276. </head>
  277. <body>
  278. </body>
  279. </html>`
  280. subscriptions, err := NewSubscriptionFinder(nil).FindSubscriptionsFromWebPage("http://example.org/", "text/html", strings.NewReader(htmlPage))
  281. if err != nil {
  282. t.Fatalf(`Parsing a correctly formatted HTML page should not return any error: %v`, err)
  283. }
  284. if len(subscriptions) != 0 {
  285. t.Fatal(`Incorrect number of subscriptions returned`)
  286. }
  287. }