You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

478 lines
22 KiB

  1. <?php
  2. use Symfony\Component\HttpFoundation\Request;
  3. use Symfony\Component\HttpFoundation\Response;
  4. class FeedTest extends PHPUnit_Framework_TestCase {
  5. private $http;
  6. public function setUp() {
  7. $this->client = new Parse();
  8. $this->client->http = new p3k\HTTP\Test(dirname(__FILE__).'/data/');
  9. $this->client->mc = null;
  10. }
  11. private function parse($params) {
  12. $request = new Request($params);
  13. $response = new Response();
  14. return $this->client->parse($request, $response);
  15. }
  16. public function testListOfHEntrys() {
  17. $url = 'http://feed.example.com/list-of-hentrys';
  18. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  19. $body = $response->getContent();
  20. $this->assertEquals(200, $response->getStatusCode());
  21. $result = json_decode($body);
  22. $this->assertEquals('mf2+html', $result->{'source-format'});
  23. $data = $result->data;
  24. $this->assertEquals('feed', $data->type);
  25. $this->assertEquals(4, count($data->items));
  26. $this->assertEquals('One', $data->items[0]->name);
  27. $this->assertEquals('article', $data->items[0]->{'post-type'});
  28. $this->assertEquals('Two', $data->items[1]->name);
  29. $this->assertEquals('article', $data->items[1]->{'post-type'});
  30. $this->assertEquals('Three', $data->items[2]->name);
  31. $this->assertEquals('Four', $data->items[3]->name);
  32. }
  33. public function testListOfHEntrysWithHCard() {
  34. $url = 'http://feed.example.com/list-of-hentrys-with-h-card';
  35. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  36. $body = $response->getContent();
  37. $this->assertEquals(200, $response->getStatusCode());
  38. $result = json_decode($body);
  39. $this->assertEquals('mf2+html', $result->{'source-format'});
  40. $data = $result->data;
  41. $this->assertEquals('feed', $data->type);
  42. $this->assertEquals(4, count($data->items));
  43. $this->assertEquals('One', $data->items[0]->name);
  44. $this->assertEquals('article', $data->items[0]->{'post-type'});
  45. $this->assertEquals('Two', $data->items[1]->name);
  46. $this->assertEquals('Three', $data->items[2]->name);
  47. $this->assertEquals('Four', $data->items[3]->name);
  48. // Check that the author h-card was matched up with each h-entry
  49. $this->assertEquals('Author Name', $data->items[0]->author->name);
  50. $this->assertEquals('Author Name', $data->items[1]->author->name);
  51. $this->assertEquals('Author Name', $data->items[2]->author->name);
  52. $this->assertEquals('Author Name', $data->items[3]->author->name);
  53. }
  54. public function testListOfHEntrysWithHCardNoExpect() {
  55. $url = 'http://feed.example.com/list-of-hentrys-with-h-card';
  56. $response = $this->parse(['url' => $url]);
  57. $body = $response->getContent();
  58. $this->assertEquals(200, $response->getStatusCode());
  59. $result = json_decode($body);
  60. $this->assertEquals('mf2+html', $result->{'source-format'});
  61. $data = $result->data;
  62. $this->assertEquals('feed', $data->type);
  63. $this->assertEquals(4, count($data->items));
  64. $this->assertEquals('One', $data->items[0]->name);
  65. $this->assertEquals('article', $data->items[0]->{'post-type'});
  66. $this->assertEquals('Two', $data->items[1]->name);
  67. $this->assertEquals('Three', $data->items[2]->name);
  68. $this->assertEquals('Four', $data->items[3]->name);
  69. // Check that the author h-card was matched up with each h-entry
  70. $this->assertEquals('Author Name', $data->items[0]->author->name);
  71. $this->assertEquals('Author Name', $data->items[1]->author->name);
  72. $this->assertEquals('Author Name', $data->items[2]->author->name);
  73. $this->assertEquals('Author Name', $data->items[3]->author->name);
  74. }
  75. public function testShortListOfHEntrysWithHCardNoExpect() {
  76. $url = 'http://feed.example.com/short-list-of-hentrys-with-h-card';
  77. $response = $this->parse(['url' => $url]);
  78. $body = $response->getContent();
  79. $this->assertEquals(200, $response->getStatusCode());
  80. $result = json_decode($body);
  81. $this->assertEquals('mf2+html', $result->{'source-format'});
  82. $data = $result->data;
  83. // In this case, this looks like a page permalink
  84. $this->assertEquals('entry', $data->type);
  85. // This test should find the h-entry rather than the h-card, because the h-card does not contain the page URL
  86. $this->assertEquals('http://feed.example.com/1', $data->url);
  87. $this->assertEquals('Author', $data->author->name);
  88. }
  89. public function testShortListOfHEntrysWithHCard() {
  90. $url = 'http://feed.example.com/short-list-of-hentrys-with-h-card';
  91. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  92. $body = $response->getContent();
  93. $this->assertEquals(200, $response->getStatusCode());
  94. $result = json_decode($body);
  95. $this->assertEquals('mf2+html', $result->{'source-format'});
  96. $data = $result->data;
  97. $this->assertEquals('feed', $data->type);
  98. // This test should find the h-entry rather than the h-card, because expect=feed
  99. $this->assertEquals('entry', $data->items[0]->type);
  100. $this->assertEquals('http://feed.example.com/1', $data->items[0]->url);
  101. $this->assertEquals('Author', $data->items[0]->author->name);
  102. }
  103. public function testTopLevelHFeed() {
  104. $url = 'http://feed.example.com/top-level-h-feed';
  105. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  106. $body = $response->getContent();
  107. $this->assertEquals(200, $response->getStatusCode());
  108. $result = json_decode($body);
  109. $this->assertEquals('mf2+html', $result->{'source-format'});
  110. $data = $result->data;
  111. $this->assertEquals('feed', $data->type);
  112. $this->assertEquals(4, count($data->items));
  113. $this->assertEquals('One', $data->items[0]->name);
  114. $this->assertEquals('Two', $data->items[1]->name);
  115. $this->assertEquals('Three', $data->items[2]->name);
  116. $this->assertEquals('Four', $data->items[3]->name);
  117. }
  118. public function testTopLevelHFeedWithChildAuthor() {
  119. $url = 'http://feed.example.com/h-feed-with-child-author';
  120. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  121. $body = $response->getContent();
  122. $this->assertEquals(200, $response->getStatusCode());
  123. $result = json_decode($body);
  124. $this->assertEquals('mf2+html', $result->{'source-format'});
  125. $data = $result->data;
  126. $this->assertEquals('feed', $data->type);
  127. $this->assertEquals(4, count($data->items));
  128. $this->assertEquals('One', $data->items[0]->name);
  129. $this->assertEquals('Two', $data->items[1]->name);
  130. $this->assertEquals('Three', $data->items[2]->name);
  131. $this->assertEquals('Four', $data->items[3]->name);
  132. $this->assertEquals('Author Name', $data->items[0]->author->name);
  133. $this->assertEquals('Author Name', $data->items[1]->author->name);
  134. $this->assertEquals('Author Name', $data->items[2]->author->name);
  135. $this->assertEquals('Author Name', $data->items[3]->author->name);
  136. }
  137. public function testHCardWithChildHEntrys() {
  138. $url = 'http://feed.example.com/h-card-with-child-h-entrys';
  139. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  140. $body = $response->getContent();
  141. $this->assertEquals(200, $response->getStatusCode());
  142. $result = json_decode($body);
  143. $this->assertEquals('mf2+html', $result->{'source-format'});
  144. $data = $result->data;
  145. $this->assertEquals('feed', $data->type);
  146. $this->assertEquals(4, count($data->items));
  147. $this->assertEquals('One', $data->items[0]->name);
  148. $this->assertEquals('Two', $data->items[1]->name);
  149. $this->assertEquals('Three', $data->items[2]->name);
  150. $this->assertEquals('Four', $data->items[3]->name);
  151. }
  152. public function testHCardWithSiblingHEntrys() {
  153. $url = 'http://feed.example.com/h-card-with-sibling-h-entrys';
  154. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  155. $body = $response->getContent();
  156. $this->assertEquals(200, $response->getStatusCode());
  157. $result = json_decode($body);
  158. $this->assertEquals('mf2+html', $result->{'source-format'});
  159. $data = $result->data;
  160. $this->assertEquals('feed', $data->type);
  161. $this->assertEquals(4, count($data->items));
  162. $this->assertEquals('One', $data->items[0]->name);
  163. $this->assertEquals('Two', $data->items[1]->name);
  164. $this->assertEquals('Three', $data->items[2]->name);
  165. $this->assertEquals('Four', $data->items[3]->name);
  166. // Check that the author h-card was matched up with each h-entry
  167. $this->assertEquals('Author Name', $data->items[0]->author->name);
  168. $this->assertEquals('Author Name', $data->items[1]->author->name);
  169. $this->assertEquals('Author Name', $data->items[2]->author->name);
  170. $this->assertEquals('Author Name', $data->items[3]->author->name);
  171. }
  172. public function testHCardWithChildHFeed() {
  173. $url = 'http://feed.example.com/h-card-with-child-h-feed';
  174. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  175. $body = $response->getContent();
  176. $this->assertEquals(200, $response->getStatusCode());
  177. $result = json_decode($body);
  178. $this->assertEquals('mf2+html', $result->{'source-format'});
  179. $data = $result->data;
  180. $this->assertEquals('feed', $data->type);
  181. $this->assertEquals(4, count($data->items));
  182. $this->assertEquals('One', $data->items[0]->name);
  183. $this->assertEquals('Two', $data->items[1]->name);
  184. $this->assertEquals('Three', $data->items[2]->name);
  185. $this->assertEquals('Four', $data->items[3]->name);
  186. // Check that the author h-card was matched up with each h-entry
  187. $this->assertEquals('Author Name', $data->items[0]->author->name);
  188. $this->assertEquals('Author Name', $data->items[1]->author->name);
  189. $this->assertEquals('Author Name', $data->items[2]->author->name);
  190. $this->assertEquals('Author Name', $data->items[3]->author->name);
  191. }
  192. public function testHCardWithChildHFeedNoExpect() {
  193. $url = 'http://feed.example.com/h-card-with-child-h-feed';
  194. $response = $this->parse(['url' => $url]);
  195. $body = $response->getContent();
  196. $this->assertEquals(200, $response->getStatusCode());
  197. $result = json_decode($body);
  198. $this->assertEquals('mf2+html', $result->{'source-format'});
  199. $data = $result->data;
  200. $this->assertEquals('card', $data->type);
  201. $this->assertEquals('Author Name', $data->name);
  202. }
  203. public function testJSONFeed() {
  204. $url = 'http://feed.example.com/jsonfeed';
  205. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  206. $body = $response->getContent();
  207. $this->assertEquals(200, $response->getStatusCode());
  208. $result = json_decode($body);
  209. $this->assertEquals('feed+json', $result->{'source-format'});
  210. $data = $result->data;
  211. $this->assertEquals(11, count($data->items));
  212. for($i=0; $i<8; $i++) {
  213. $this->assertEquals('entry', $data->items[$i]->type);
  214. $this->assertEquals('manton', $data->items[$i]->author->name);
  215. $this->assertEquals('http://www.manton.org', $data->items[$i]->author->url);
  216. $this->assertNotEmpty($data->items[$i]->url);
  217. $this->assertNotEmpty($data->items[$i]->uid);
  218. $this->assertNotEmpty($data->items[$i]->published);
  219. $this->assertNotEmpty($data->items[$i]->content->html);
  220. $this->assertNotEmpty($data->items[$i]->content->text);
  221. }
  222. $this->assertEquals('note', $data->items[0]->{'post-type'});
  223. $this->assertEquals('article', $data->items[4]->{'post-type'});
  224. $this->assertEquals('<p>Coming up on a year since I wrote about how <a href="http://www.manton.org/2016/11/todays-social-networks-are-broken.html">today’s social networks are broken</a>. Still what I believe.</p>', $data->items[7]->content->html);
  225. $this->assertEquals('Coming up on a year since I wrote about how today’s social networks are broken. Still what I believe.', $data->items[7]->content->text);
  226. $this->assertEquals('http://www.manton.org/2017/11/5979.html', $data->items[7]->url);
  227. $this->assertEquals('http://www.manton.org/2017/11/5979.html', $data->items[7]->uid);
  228. $this->assertEquals('2017-11-07T21:00:42+00:00', $data->items[7]->published);
  229. $this->assertEquals('feed', $data->type);
  230. }
  231. public function testJSONFeedFallbackAuthor() {
  232. $url = 'http://feed.example.com/jsonfeed-author';
  233. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  234. $body = $response->getContent();
  235. $this->assertEquals(200, $response->getStatusCode());
  236. $result = json_decode($body);
  237. $this->assertEquals('feed+json', $result->{'source-format'});
  238. $data = $result->data;
  239. $this->assertEquals(11, count($data->items));
  240. for($i=0; $i<8; $i++) {
  241. $this->assertEquals('entry', $data->items[$i]->type);
  242. $this->assertEquals('Manton Reece', $data->items[$i]->author->name);
  243. $this->assertEquals('https://www.manton.org/', $data->items[$i]->author->url);
  244. $this->assertEquals('https://micro.blog/manton/avatar.jpg', $data->items[$i]->author->photo);
  245. }
  246. }
  247. public function testJSONFeedRelativeImages() {
  248. $url = 'http://feed.example.com/jsonfeed';
  249. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  250. $body = $response->getContent();
  251. $this->assertEquals(200, $response->getStatusCode());
  252. $result = json_decode($body);
  253. $this->assertEquals('feed+json', $result->{'source-format'});
  254. $data = $result->data;
  255. // Relative image on an item that has a url
  256. $this->assertEquals('http://www.manton.org/2017/11/image.jpg', $data->items[9]->photo[0]);
  257. // Relative image on an item that has no URL, fall back to feed URL
  258. $this->assertEquals('http://feed.example.com/image.jpg', $data->items[10]->photo[0]);
  259. // Relative image inside the content html
  260. $this->assertContains('http://www.manton.org/2017/11/img.jpg', $data->items[9]->content->html);
  261. }
  262. public function testAtomFeed() {
  263. $url = 'http://feed.example.com/atom';
  264. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  265. $body = $response->getContent();
  266. $this->assertEquals(200, $response->getStatusCode());
  267. $result = json_decode($body);
  268. $this->assertEquals('xml', $result->{'source-format'});
  269. $data = $result->data;
  270. $this->assertEquals(8, count($data->items));
  271. for($i=0; $i<8; $i++) {
  272. $this->assertEquals('entry', $data->items[$i]->type);
  273. $this->assertEquals('note', $data->items[$i]->{'post-type'});
  274. $this->assertEquals('Tantek', $data->items[$i]->author->name);
  275. $this->assertEquals('http://tantek.com/', $data->items[$i]->author->url);
  276. $this->assertNotEmpty($data->items[$i]->url);
  277. $this->assertNotEmpty($data->items[$i]->published);
  278. $this->assertNotEmpty($data->items[$i]->content->html);
  279. $this->assertNotEmpty($data->items[$i]->content->text);
  280. }
  281. $this->assertEquals('2017-11-08T23:53:00-08:00', $data->items[0]->published);
  282. $this->assertEquals('http://tantek.com/2017/312/t3/tam-trail-run-first-trail-half', $data->items[0]->url);
  283. $this->assertEquals('went to MORE Pancakes! this morning @RunJanji pop-up on California st after #NPSF. Picked up a new running shirt.', $data->items[1]->content->text);
  284. $this->assertEquals('went to MORE Pancakes! this morning <a href="https://twitter.com/RunJanji">@RunJanji</a> pop-up on California st after #NPSF. Picked up a new running shirt.', $data->items[1]->content->html);
  285. $this->assertEquals('feed', $data->type);
  286. }
  287. public function testRSSFeed() {
  288. $url = 'http://feed.example.com/rss';
  289. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  290. $body = $response->getContent();
  291. $this->assertEquals(200, $response->getStatusCode());
  292. $result = json_decode($body);
  293. $this->assertEquals('xml', $result->{'source-format'});
  294. $data = $result->data;
  295. $this->assertEquals(10, count($data->items));
  296. for($i=0; $i<10; $i++) {
  297. $this->assertEquals('entry', $data->items[$i]->type);
  298. $this->assertEquals('note', $data->items[$i]->{'post-type'});
  299. $this->assertEquals('Ryan Barrett', $data->items[$i]->author->name);
  300. $this->assertEquals('https://snarfed.org/', $data->items[$i]->author->url);
  301. $this->assertNotEmpty($data->items[$i]->url);
  302. $this->assertNotEmpty($data->items[$i]->published);
  303. $this->assertNotEmpty($data->items[$i]->content->html);
  304. if($i > 1)
  305. $this->assertNotEmpty($data->items[$i]->content->text);
  306. }
  307. $this->assertEquals('2017-09-12T20:09:12+00:00', $data->items[9]->published);
  308. $this->assertEquals('https://snarfed.org/2017-09-12_25492', $data->items[9]->url);
  309. $this->assertEquals('<p>new business cards <img src="https://s.w.org/images/core/emoji/2.3/72x72/1f602.png" alt="😂" /></p>
  310. <p><img src="https://i0.wp.com/snarfed.org/w/wp-content/uploads/2017/09/IMG_20170912_131414_767.jpg?w=696&amp;ssl=1" alt="IMG_20170912_131414_767.jpg?w=696&amp;ssl=1" /></p>', $data->items[9]->content->html);
  311. $this->assertEquals('new business cards', $data->items[9]->content->text);
  312. $this->assertEquals('feed', $data->type);
  313. }
  314. public function testPodcastFeed() {
  315. $url = 'http://feed.example.com/podcast-rss';
  316. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  317. $body = $response->getContent();
  318. $this->assertEquals(200, $response->getStatusCode());
  319. $result = json_decode($body);
  320. $this->assertEquals('xml', $result->{'source-format'});
  321. $data = $result->data;
  322. $this->assertEquals(12, count($data->items));
  323. for($i=0; $i<12; $i++) {
  324. $this->assertEquals('entry', $data->items[$i]->type);
  325. $this->assertEquals('audio', $data->items[$i]->{'post-type'});
  326. $this->assertEquals('Aaron Parecki', $data->items[$i]->author->name);
  327. $this->assertEquals('https://percolator.today/', $data->items[$i]->author->url);
  328. $this->assertNotEmpty($data->items[$i]->url);
  329. $this->assertNotEmpty($data->items[$i]->published);
  330. $this->assertNotEmpty($data->items[$i]->name);
  331. $this->assertNotEmpty($data->items[$i]->content->html);
  332. $this->assertNotEmpty($data->items[$i]->content->text);
  333. $this->assertNotEmpty($data->items[$i]->audio);
  334. }
  335. $this->assertEquals('Episode 1: Welcome', $data->items[11]->name);
  336. $this->assertEquals('https://percolator.today/episode/1', $data->items[11]->url);
  337. $this->assertEquals('2017-09-20T07:00:00+00:00', $data->items[11]->published);
  338. $this->assertEquals('https://percolator.today/redirect.php?url=https%3A%2F%2Fpercolator.today%2Fmedia%2FPercolator_Episode_1.mp3', $data->items[11]->audio[0]);
  339. $this->assertContains('What is Percolator? Some thoughts about multi-photos in Instagram.', $data->items[11]->content->text);
  340. $this->assertContains('What is Percolator? Some thoughts about multi-photos in Instagram.', $data->items[11]->content->html);
  341. $this->assertContains('<li><a href="https://indieweb.org/multi-photo_vs_collection">multi-photo vs collection</a></li>', $data->items[11]->content->html);
  342. $this->assertEquals('feed', $data->type);
  343. }
  344. public function testInstagramAtomFeed() {
  345. $url = 'http://feed.example.com/instagram-atom';
  346. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  347. $body = $response->getContent();
  348. $this->assertEquals(200, $response->getStatusCode());
  349. $result = json_decode($body);
  350. $this->assertEquals('xml', $result->{'source-format'});
  351. $data = $result->data;
  352. $this->assertEquals(12, count($data->items));
  353. $this->assertEquals('Marshall Kirkpatrick', $data->items[11]->author->name);
  354. $this->assertEquals('https://www.instagram.com/marshallk/', $data->items[11]->author->url);
  355. $this->assertEquals('https://www.instagram.com/p/BcFjw9SHYql/', $data->items[11]->url);
  356. $this->assertEquals('2017-11-29T17:04:00+00:00', $data->items[11]->published);
  357. // Should remove the "name" since it's a prefix of the content
  358. $this->assertObjectNotHasAttribute('name', $data->items[11]);
  359. $this->assertEquals('Sometimes my job requires me to listen to 55 minutes of an hour long phone call while I go for a long walk on a sunny morning and wait for my turn to give an update. Pretty nice!', $data->items[11]->content->text);
  360. }
  361. public function testAscraeus() {
  362. $url = 'http://source.example.com/ascraeus';
  363. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  364. $body = $response->getContent();
  365. $this->assertEquals(200, $response->getStatusCode());
  366. $data = json_decode($body)->data;
  367. $this->assertEquals('feed', $data->type);
  368. $this->assertEquals(20, count($data->items));
  369. }
  370. public function testAdactioLinks() {
  371. $url = 'http://feed.example.com/adactio-links';
  372. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  373. $body = $response->getContent();
  374. $this->assertEquals(200, $response->getStatusCode());
  375. $data = json_decode($body)->data;
  376. $this->assertEquals('feed', $data->type);
  377. // 20 h-entrys followed by one h-card, which should have been removed and used as the author instead
  378. $this->assertEquals(20, count($data->items));
  379. $this->assertEquals('http://feed.example.com/links/14501', $data->items[0]->url);
  380. $this->assertEquals('http://feed.example.com/links/14445', $data->items[19]->url);
  381. $item = $data->items[0];
  382. $this->assertEquals('Jeremy Keith', $item->author->name);
  383. $this->assertEquals('https://adactio.com/', $item->author->url);
  384. }
  385. public function testWaterpigsFeed() {
  386. $url = 'http://feed.example.com/waterpigs';
  387. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  388. $body = $response->getContent();
  389. $this->assertEquals(200, $response->getStatusCode());
  390. $data = json_decode($body)->data;
  391. $this->assertEquals('feed', $data->type);
  392. $this->assertEquals(21, count($data->items));
  393. $item = $data->items[16];
  394. $this->assertEquals('Barnaby Walters', $item->author->name);
  395. $this->assertEquals('https://waterpigs.co.uk', $item->author->url);
  396. }
  397. public function testRSSWithNoXMLTag() {
  398. $url = 'http://feed.example.com/rss-no-xml-tag';
  399. $response = $this->parse(['url' => $url, 'expect' => 'feed']);
  400. $body = $response->getContent();
  401. $this->assertEquals(200, $response->getStatusCode());
  402. $data = json_decode($body)->data;
  403. $this->assertEquals('feed', $data->type);
  404. }
  405. }