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.

277 lines
14 KiB

  1. <?php
  2. use Symfony\Component\HttpFoundation\Request;
  3. use Symfony\Component\HttpFoundation\Response;
  4. class APITest extends PHPUnit_Framework_TestCase {
  5. private $client;
  6. public function setUp() {
  7. $this->client = new API();
  8. $this->client->http = new Telegraph\HTTPTest(dirname(__FILE__).'/data/');
  9. ORM::for_table('users')->raw_query('TRUNCATE users')->delete_many();
  10. ORM::for_table('roles')->raw_query('TRUNCATE roles')->delete_many();
  11. ORM::for_table('sites')->raw_query('TRUNCATE sites')->delete_many();
  12. ORM::for_table('webmentions')->raw_query('TRUNCATE webmentions')->delete_many();
  13. ORM::for_table('webmention_status')->raw_query('TRUNCATE webmention_status')->delete_many();
  14. }
  15. private function webmention($params) {
  16. $request = new Request($params);
  17. $response = new Response();
  18. return $this->client->webmention($request, $response);
  19. }
  20. private function superfeedr_tracker($content, $args) {
  21. $request = new Request();
  22. $request->initialize([], [], [], [], [], [], $content);
  23. $response = new Response();
  24. return $this->client->superfeedr_tracker($request, $response, $args);
  25. }
  26. private function status($code) {
  27. $request = new Request();
  28. $response = new Response();
  29. return $this->client->webmention_status($request, $response, ['code'=>$code]);
  30. }
  31. private function _createExampleAccount() {
  32. $user = ORM::for_table('users')->create();
  33. $user->url = 'http://example.com';
  34. $user->save();
  35. $site = ORM::for_table('sites')->create();
  36. $site->name = 'Example';
  37. $site->url = 'http://example.com';
  38. $site->created_by = $user->id();
  39. $site->save();
  40. $role = ORM::for_table('roles')->create();
  41. $role->site_id = $site->id();
  42. $role->user_id = $user->id();
  43. $role->role = 'owner';
  44. $role->token = 'a';
  45. $role->save();
  46. }
  47. private function _assertQueued($source, $target, $status_url) {
  48. preg_match('/\/webmention\/(.+)/', $status_url, $match);
  49. $this->assertNotNull($match);
  50. # Verify it queued the mention in the database
  51. $d = ORM::for_table('webmentions')->where(['source' => $source, 'target' => $target])->find_one();
  52. $this->assertNotFalse($d);
  53. $this->assertEquals($match[1], $d->token);
  54. # Check the status endpoint to make sure it says it's still queued
  55. $response = $this->status($d->token);
  56. $this->assertEquals(200, $response->getStatusCode());
  57. $data = json_decode($response->getContent());
  58. $this->assertEquals('queued', $data->status);
  59. }
  60. private function _assertNotQueued($source, $target) {
  61. # Verify it did not queue a mention in the database
  62. $d = ORM::for_table('webmentions')->where(['source' => $source, 'target' => $target])->find_one();
  63. $this->assertFalse($d);
  64. }
  65. public function testAuthentication() {
  66. $response = $this->webmention([]);
  67. $this->assertEquals(401, $response->getStatusCode());
  68. $data = json_decode($response->getContent());
  69. $this->assertEquals('authentication_required', $data->error);
  70. $this->_createExampleAccount();
  71. $response = $this->webmention(['token'=>'x','source'=>'http://source.example','target'=>'http://target.example']);
  72. $this->assertEquals(401, $response->getStatusCode());
  73. $data = json_decode($response->getContent());
  74. $this->assertEquals('invalid_token', $data->error);
  75. $response = $this->webmention(['token'=>'a']);
  76. $this->assertEquals(400, $response->getStatusCode());
  77. $data = json_decode($response->getContent());
  78. $this->assertEquals('missing_parameters', $data->error);
  79. }
  80. public function testMissingParameters() {
  81. $this->_createExampleAccount();
  82. $response = $this->webmention(['token'=>'a']);
  83. $this->assertEquals(400, $response->getStatusCode());
  84. $data = json_decode($response->getContent());
  85. $this->assertEquals('missing_parameters', $data->error);
  86. $response = $this->webmention(['token'=>'a','source'=>'foo']);
  87. $this->assertEquals(400, $response->getStatusCode());
  88. $data = json_decode($response->getContent());
  89. $this->assertEquals('missing_parameters', $data->error);
  90. $response = $this->webmention(['token'=>'a','target'=>'foo']);
  91. $this->assertEquals(400, $response->getStatusCode());
  92. $data = json_decode($response->getContent());
  93. $this->assertEquals('missing_parameters', $data->error);
  94. $response = $this->webmention(['token'=>'a','target_domain'=>'foo']);
  95. $this->assertEquals(400, $response->getStatusCode());
  96. $data = json_decode($response->getContent());
  97. $this->assertEquals('missing_parameters', $data->error);
  98. }
  99. public function testTargetAndTargetDomain() {
  100. $this->_createExampleAccount();
  101. $response = $this->webmention(['token'=>'a','source'=>'foo','target'=>'foo','target_domain'=>'foo']);
  102. $this->assertEquals(400, $response->getStatusCode());
  103. $data = json_decode($response->getContent());
  104. $this->assertEquals('invalid_parameter', $data->error);
  105. }
  106. public function testInvalidURLs() {
  107. $this->_createExampleAccount();
  108. foreach ([['token'=>'a','source'=>'notaurl','target'=>'alsonotaurl'],
  109. ['token'=>'a','source'=>'http://source.example','target'=>'alsonotaurl'],
  110. ['token'=>'a','source'=>'notaurl','target'=>'http://target.example'],
  111. ['token'=>'a','source'=>'http://source.example','target'=>'mailto:user@example.com'],
  112. ['token'=>'a','source'=>'http://source.example','target'=>'http://target.example','callback'=>'notaurl']
  113. ] as $params) {
  114. $response = $this->webmention($params);
  115. $this->assertEquals(400, $response->getStatusCode());
  116. $data = json_decode($response->getContent());
  117. $this->assertEquals('invalid_parameter', $data->error);
  118. }
  119. }
  120. public function testNoLinkToSource() {
  121. $this->_createExampleAccount();
  122. $response = $this->webmention(['token'=>'a','source'=>'http://source.example.com/nolink','target'=>'http://target.example.com']);
  123. $this->assertEquals(400, $response->getStatusCode());
  124. $data = json_decode($response->getContent());
  125. $this->assertEquals('no_link_found', $data->error);
  126. $response = $this->webmention(['token'=>'a','source'=>'http://source.example.com/nothtml','target'=>'http://target.example.com']);
  127. $this->assertEquals(400, $response->getStatusCode());
  128. $data = json_decode($response->getContent());
  129. $this->assertEquals('no_link_found', $data->error);
  130. }
  131. public function testHandlesMalformedHTMLWithLink() {
  132. $this->_createExampleAccount();
  133. $response = $this->webmention(['token'=>'a','source'=>'http://source.example.com/invalidhtml','target'=>'http://target.example.com']);
  134. $this->assertEquals(201, $response->getStatusCode());
  135. $data = json_decode($response->getContent());
  136. $this->assertEquals(false, property_exists($data, 'error'));
  137. }
  138. public function testTargetQueuesWebmention() {
  139. $this->_createExampleAccount();
  140. $response = $this->webmention(['token'=>'a','source'=>'http://source.example.com/basictest','target'=>'http://target.example.com']);
  141. $this->assertEquals(201, $response->getStatusCode());
  142. $data = json_decode($response->getContent());
  143. $this->assertEquals(false, property_exists($data, 'error'));
  144. $this->assertEquals('queued', $data->status);
  145. $this->_assertQueued('http://source.example.com/basictest', 'http://target.example.com', $data->location);
  146. }
  147. public function testTargetQueuesOnlyTargetWebmention() {
  148. $this->_createExampleAccount();
  149. $response = $this->webmention(['token'=>'a','source'=>'http://source.example.com/multipletest','target'=>'http://target.example.com']);
  150. $this->assertEquals(201, $response->getStatusCode());
  151. $data = json_decode($response->getContent());
  152. $this->assertEquals(false, property_exists($data, 'error'));
  153. $this->assertEquals('queued', $data->status);
  154. $this->_assertQueued('http://source.example.com/multipletest', 'http://target.example.com', $data->location);
  155. $this->_assertNotQueued('http://source.example.com/multipletest', '/relativelink');
  156. }
  157. public function testTargetDomainQueuesOneWebmention() {
  158. $this->_createExampleAccount();
  159. $response = $this->webmention(['token'=>'a','source'=>'http://source.example.com/basictest','target_domain'=>'target.example.com']);
  160. $body = $response->getContent();
  161. $this->assertEquals(201, $response->getStatusCode(), $body);
  162. $data = json_decode($body);
  163. $this->assertEquals(false, property_exists($data, 'error'), $body);
  164. $this->assertEquals('queued', $data->status, $body);
  165. $this->assertEquals(true, property_exists($data, 'location'), $body);
  166. $this->assertEquals(1, count($data->location), $body);
  167. $this->_assertQueued('http://source.example.com/basictest', 'http://target.example.com', $data->location[0]);
  168. }
  169. public function testTargetDomainQueuesMultipleWebmentions() {
  170. $this->_createExampleAccount();
  171. $response = $this->webmention(['token'=>'a','source'=>'http://source.example.com/basictest','target_domain'=>'example.com']);
  172. $body = $response->getContent();
  173. $this->assertEquals(201, $response->getStatusCode(), $body);
  174. $data = json_decode($body);
  175. $this->assertEquals(false, property_exists($data, 'error'), $body);
  176. $this->assertEquals('queued', $data->status, $body);
  177. $this->assertEquals(2, count($data->location), $body);
  178. $this->_assertQueued('http://source.example.com/basictest', 'http://target.example.com', $data->location[0]);
  179. $this->_assertQueued('http://source.example.com/basictest', 'http://target2.example.com', $data->location[1]);
  180. }
  181. public function testTargetDomainQueuesOnlyWebmentionsFromTargetDomain() {
  182. $this->_createExampleAccount();
  183. $response = $this->webmention(['token'=>'a','source'=>'http://source.example.com/multipletest','target_domain'=>'example.com']);
  184. $body = $response->getContent();
  185. $this->assertEquals(201, $response->getStatusCode(), $body);
  186. $data = json_decode($body);
  187. $this->assertEquals(false, property_exists($data, 'error'), $body);
  188. $this->assertEquals('queued', $data->status, $body);
  189. $this->assertEquals(2, count($data->location), $body);
  190. $this->_assertQueued('http://source.example.com/multipletest', 'http://target.example.com', $data->location[0]);
  191. $this->_assertQueued('http://source.example.com/multipletest', 'http://target2.example.com', $data->location[1]);
  192. $this->_assertNotQueued('http://source.example.com/multipletest', 'http://target.example.org');
  193. $this->_assertNotQueued('http://source.example.com/multipletest', '/relativelink');
  194. $this->_assertNotQueued('http://source.example.com/multipletest', 'http://source.example.com/relativelink');
  195. }
  196. public function testTargetDomainSubdomainCheck() {
  197. $this->_createExampleAccount();
  198. $response = $this->webmention(['token'=>'a','source'=>'http://source.example.com/multipletest','target_domain'=>'ample.com']);
  199. $body = $response->getContent();
  200. $this->assertEquals(400, $response->getStatusCode());
  201. $data = json_decode($response->getContent());
  202. $this->assertEquals('no_link_found', $data->error);
  203. }
  204. public function testTargetDomainCantMatchSourceDomain() {
  205. $this->_createExampleAccount();
  206. $response = $this->webmention(['token'=>'a','source'=>'http://example.com/test','target_domain'=>'example.com']);
  207. $body = $response->getContent();
  208. $this->assertEquals(200, $response->getStatusCode());
  209. $data = json_decode($response->getContent());
  210. $this->assertEquals('not_supported', $data->error);
  211. }
  212. public function testStatusNotFound() {
  213. $this->_createExampleAccount();
  214. $response = $this->status('foo');
  215. $this->assertEquals(404, $response->getStatusCode());
  216. $data = json_decode($response->getContent());
  217. $this->assertEquals('not_found', $data->status);
  218. }
  219. public function testSuperfeedrTracker() {
  220. $this->_createExampleAccount();
  221. $payload = '{"status":{"code":200,"http":"Track feed","nextFetch":1238466305,"period":900,"lastFetch":1238466305,"lastParse":1238466305,"lastMaintenanceAt":1238466305,"feed":"http:\/\/track.superfeedr.com\/?query=indieweb"},"title":"","updated":1454695477,"id":"","items":[{"id":"http:\/\/werd.io\/2016\/im-so-used-to-posting-on-my-own-site-first","published":1454690643,"updated":1454690643,"title":"I\'m so used to posting on my own site first and syndicating to Twitter and Facebook that I\'d find it so weird to post natively.","summary":"<div class=\"\">\n <p class=\"p-name\">I&#039;m so used to posting on my own site first and syndicating to Twitter and Facebook that I&#039;d find it so weird to post natively. <a href=\"http:\/\/werd.io\/tag\/indieweb\" class=\"p-category\" rel=\"tag\">#indieweb<\/a><\/p>\n<\/div>","permalinkUrl":"http://source.example.com/basictest","standardLinks":{"alternate":[{"title":"I\'m so used to posting on my own site first and syndicating to Twitter and Facebook that I\'d find it so weird to post natively.","rel":"alternate","href":"http:\/\/werd.io\/2016\/im-so-used-to-posting-on-my-own-site-first","type":"text\/html"}]},"actor":{"displayName":"Ben Werdm\u00fcller","id":"ben-werdm-ller"},"categories":["#indieweb"],"source":{"id":"ben-werdm-ller-2016-2-5-18","title":"Ben Werdm\u00fcller","updated":1454695469,"permalinkUrl":"http:\/\/werd.io\/content\/all","standardLinks":{"alternate":[{"title":"Ben Werdm\u00fcller","rel":"alternate","href":"http:\/\/werd.io\/content\/all","type":"text\/html"}],"hub":[{"title":"","rel":"hub","href":"http:\/\/benwerd.superfeedr.com\/","type":"text\/html"}],"self":[{"title":"Ben Werdm\u00fcller","rel":"self","href":"http:\/\/werd.io\/content\/all?_t=rss","type":"application\/rss+xml"}]},"status":{"code":200,"http":"","nextFetch":1454776929,"lastFetch":1454695477,"lastParse":1454695477,"lastMaintenanceAt":1454627737,"period":86400,"velocity":10.5,"popularity":0.97363835294308,"bozoRank":0.1,"entriesCountSinceLastMaintenance":7,"feed":"http:\/\/werd.io\/content\/all?_t=rss"}}}]}';
  222. $response = $this->superfeedr_tracker($payload, ['token'=>'a']);
  223. $this->assertEquals(201, $response->getStatusCode());
  224. $data = json_decode($response->getContent());
  225. $this->assertEquals('queued', $data->status);
  226. }
  227. }