Do not use STDOUT and STDERR constants
[phinde.git] / tests / HubUrlExtractorTest.php
1 <?php
2 class HubUrlExtractorTest extends \PHPUnit\Framework\TestCase
3 {
4     public function testGetUrlsHEAD()
5     {
6         $mock = new HTTP_Request2_Adapter_Mock();
7         $this->addResponse(
8             $mock,
9             "HTTP/1.0 200 OK\r\n"
10             . "Content-type: text/html\r\n"
11             . "Link: <https://hub.example.com/>; rel=\"hub\"\r\n"
12             . "Link: <http://example.com/feed>; rel=\"self\"\r\n"
13             . "\r\n",
14             'http://example.org/'
15         );
16
17         $extractor = new phinde\HubUrlExtractor();
18         $extractor->setRequestTemplate(
19             new HTTP_Request2(null, null, ['adapter' => $mock])
20         );
21
22         $this->assertEquals(
23             [
24                 'hub'  => ['https://hub.example.com/'],
25                 'self' => 'http://example.com/feed',
26             ],
27             $extractor->getUrls('http://example.org/')
28         );
29     }
30
31     public function testGetUrlsMultipleHubsHEAD()
32     {
33         $mock = new HTTP_Request2_Adapter_Mock();
34         $this->addResponse(
35             $mock,
36             "HTTP/1.0 200 OK\r\n"
37             . "Content-type: text/html\r\n"
38             . "Link: <https://hub.example.com/>; rel=\"hub\"\r\n"
39             . "Link: <https://hub2.example.com/>; rel=\"hub\"\r\n"
40             . "Link: <http://example.com/feed>; rel=\"self\"\r\n"
41             . "Link: <https://hub3.example.com/>; rel=\"hub\"\r\n"
42             . "\r\n",
43             'http://example.org/'
44         );
45
46         $extractor = new phinde\HubUrlExtractor();
47         $extractor->setRequestTemplate(
48             new HTTP_Request2(null, null, ['adapter' => $mock])
49         );
50
51         $this->assertEquals(
52             [
53                 'hub'  => [
54                     'https://hub.example.com/',
55                     'https://hub2.example.com/',
56                     'https://hub3.example.com/',
57                 ],
58                 'self' => 'http://example.com/feed',
59             ],
60             $extractor->getUrls('http://example.org/')
61         );
62     }
63
64     public function testGetUrlsHtml()
65     {
66         $mock = new HTTP_Request2_Adapter_Mock();
67         //HEAD
68         $this->addResponse(
69             $mock,
70             "HTTP/1.0 200 OK\r\n"
71             . "Content-type: text/html\r\n"
72             . "\r\n",
73             'http://example.org/'
74         );
75         //HEAD
76         $this->addResponse(
77             $mock,
78             "HTTP/1.0 200 OK\r\n"
79             . "Content-type: text/html\r\n"
80             . "\r\n"
81             . <<<HTM
82 <html>
83  <head>
84   <link rel='hub' href='https://hub.example.com/'/>
85   <link rel='self' href='http://example.com/feed'/>
86  </head>
87 </html>
88 HTM,
89             'http://example.org/'
90         );
91
92         $extractor = new phinde\HubUrlExtractor();
93         $extractor->setRequestTemplate(
94             new HTTP_Request2(null, null, ['adapter' => $mock])
95         );
96
97         $this->assertEquals(
98             [
99                 'hub'  => ['https://hub.example.com/'],
100                 'self' => 'http://example.com/feed',
101             ],
102             $extractor->getUrls('http://example.org/')
103         );
104     }
105
106     public function testGetUrlsHtmlMultipleHubs()
107     {
108         $mock = new HTTP_Request2_Adapter_Mock();
109         //HEAD
110         $this->addResponse(
111             $mock,
112             "HTTP/1.0 200 OK\r\n"
113             . "Content-type: text/html\r\n"
114             . "\r\n",
115             'http://example.org/'
116         );
117         //HEAD
118         $this->addResponse(
119             $mock,
120             "HTTP/1.0 200 OK\r\n"
121             . "Content-type: text/html\r\n"
122             . "\r\n"
123             . <<<HTM
124 <html>
125  <head>
126   <link rel='hub' href='https://hub.example.com/'/>
127   <link rel='hub' href='https://hub2.example.com/'/>
128   <link rel='self' href='http://example.com/feed'/>
129  </head>
130 </html>
131 HTM,
132             'http://example.org/'
133         );
134
135         $extractor = new phinde\HubUrlExtractor();
136         $extractor->setRequestTemplate(
137             new HTTP_Request2(null, null, ['adapter' => $mock])
138         );
139
140         $this->assertEquals(
141             [
142                 'hub'  => [
143                     'https://hub.example.com/',
144                     'https://hub2.example.com/',
145                 ],
146                 'self' => 'http://example.com/feed',
147             ],
148             $extractor->getUrls('http://example.org/')
149         );
150     }
151
152     public function testGetUrlsXHtml()
153     {
154         $mock = new HTTP_Request2_Adapter_Mock();
155         //HEAD
156         $this->addResponse(
157             $mock,
158             "HTTP/1.0 200 OK\r\n"
159             . "Content-type: application/xhtml+xml\r\n"
160             . "\r\n",
161             'http://example.org/'
162         );
163         //HEAD
164         $this->addResponse(
165             $mock,
166             "HTTP/1.0 200 OK\r\n"
167             . "Content-type: application/xhtml+xml\r\n"
168             . "\r\n"
169             . <<<HTM
170 <html>
171  <head>
172   <link rel='hub' href='https://hub.example.com/'/>
173   <link rel='self' href='http://example.com/feed'/>
174  </head>
175 </html>
176 HTM,
177             'http://example.org/'
178         );
179
180         $extractor = new phinde\HubUrlExtractor();
181         $extractor->setRequestTemplate(
182             new HTTP_Request2(null, null, ['adapter' => $mock])
183         );
184
185         $this->assertEquals(
186             [
187                 'hub'  => ['https://hub.example.com/'],
188                 'self' => 'http://example.com/feed',
189             ],
190             $extractor->getUrls('http://example.org/')
191         );
192     }
193
194     public function testGetUrlsAtom()
195     {
196         $mock = new HTTP_Request2_Adapter_Mock();
197         //HEAD
198         $this->addResponse(
199             $mock,
200             "HTTP/1.0 200 OK\r\n"
201             . "Content-type: application/atom+xml\r\n"
202             . "\r\n",
203             'http://example.org/'
204         );
205         //HEAD
206         $this->addResponse(
207             $mock,
208             "HTTP/1.0 200 OK\r\n"
209             . "Content-type: application/atom+xml\r\n"
210             . "\r\n"
211             . <<<HTM
212 <?xml version="1.0" encoding="utf-8"?>
213 <feed xmlns="http://www.w3.org/2005/Atom">
214  <link href="http://example.org/"/>
215  <link rel="self" href="http://example.com/feed"/>
216  <link rel="hub" href="https://hub.example.com/"/>
217 </feed>
218 HTM,
219             'http://example.org/'
220         );
221
222         $extractor = new phinde\HubUrlExtractor();
223         $extractor->setRequestTemplate(
224             new HTTP_Request2(null, null, ['adapter' => $mock])
225         );
226
227         $this->assertEquals(
228             [
229                 'hub'  => ['https://hub.example.com/'],
230                 'self' => 'http://example.com/feed',
231             ],
232             $extractor->getUrls('http://example.org/')
233         );
234     }
235
236     public function testGetUrlsRss2()
237     {
238         $mock = new HTTP_Request2_Adapter_Mock();
239         //HEAD
240         $this->addResponse(
241             $mock,
242             "HTTP/1.0 200 OK\r\n"
243             . "Content-type: application/rss+xml\r\n"
244             . "\r\n",
245             'http://example.org/'
246         );
247         //HEAD
248         $this->addResponse(
249             $mock,
250             "HTTP/1.0 200 OK\r\n"
251             . "Content-type: application/rss+xml\r\n"
252             . "\r\n"
253             . <<<HTM
254 <?xml version="1.0" encoding="utf-8"?>
255 <rss version="2.0">
256  <channel>
257   <link>http://www.example.com/main.html</link>
258   <link rel="self" href="http://example.com/feed"/>
259   <link rel="hub" href="https://hub.example.com/"/>
260  </channel>
261 </rss>
262 HTM,
263             'http://example.org/'
264         );
265
266         $extractor = new phinde\HubUrlExtractor();
267         $extractor->setRequestTemplate(
268             new HTTP_Request2(null, null, ['adapter' => $mock])
269         );
270
271         $this->assertEquals(
272             [
273                 'hub'  => ['https://hub.example.com/'],
274                 'self' => 'http://example.com/feed',
275             ],
276             $extractor->getUrls('http://example.org/')
277         );
278     }
279
280     public function testGetUrlsRss2WebLinking()
281     {
282         $mock = new HTTP_Request2_Adapter_Mock();
283         //HEAD
284         $this->addResponse(
285             $mock,
286             "HTTP/1.0 200 OK\r\n"
287             . "Content-type: application/rss+xml\r\n"
288             . "\r\n",
289             'http://example.org/'
290         );
291         //HEAD
292         $this->addResponse(
293             $mock,
294             "HTTP/1.0 200 OK\r\n"
295             . "Content-type: application/rss+xml\r\n"
296             . "\r\n"
297             . <<<HTM
298 <?xml version="1.0" encoding="utf-8"?>
299 <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
300  <channel>
301   <link>http://www.example.com/main.html</link>
302   <atom:link rel="self" href="http://example.com/feed"/>
303   <atom:link rel="hub" href="https://hub.example.com/"/>
304  </channel>
305 </rss>
306 HTM,
307             'http://example.org/'
308         );
309
310         $extractor = new phinde\HubUrlExtractor();
311         $extractor->setRequestTemplate(
312             new HTTP_Request2(null, null, ['adapter' => $mock])
313         );
314
315         $this->assertEquals(
316             [
317                 'hub'  => ['https://hub.example.com/'],
318                 'self' => 'http://example.com/feed',
319             ],
320             $extractor->getUrls('http://example.org/')
321         );
322     }
323
324     protected function addResponse($mock, $responseContent, $effectiveUrl)
325     {
326         $mock->addResponse(
327             static::createResponseFromString($responseContent, $effectiveUrl)
328         );
329     }
330
331     public static function createResponseFromString($str, $effectiveUrl)
332     {
333         $parts       = preg_split('!(\r?\n){2}!m', $str, 2);
334         $headerLines = explode("\n", $parts[0]);
335         $response    = new HTTP_Request2_Response(
336             array_shift($headerLines), true, $effectiveUrl
337         );
338         foreach ($headerLines as $headerLine) {
339             $response->parseHeaderLine($headerLine);
340         }
341         $response->parseHeaderLine('');
342         if (isset($parts[1])) {
343             $response->appendBody($parts[1]);
344         }
345         return $response;
346     }
347
348     /**
349      * It is possible to subscribe to URLs that redirect if
350      * they have a hub and self links in the HTTP headers.
351      * If they don't, we need to follow the redirect.
352      */
353     public function testGetUrlsHEADLinksForRedirect()
354     {
355         $mock = new HTTP_Request2_Adapter_Mock();
356         $this->addResponse(
357             $mock,
358             "HTTP/1.0 307 Temporary Redirect\r\n"
359             . "Content-type: text/html\r\n"
360             . "Location: http://example.org/redir-target\r\n"
361             . "Link: <https://hub.example.com/>; rel=\"hub\"\r\n"
362             . "Link: <http://example.com/feed>; rel=\"self\"\r\n"
363             . "\r\n",
364             'http://example.org/'
365         );
366         $this->addResponse(
367             $mock,
368             "HTTP/1.0 200 OK\r\n"
369             . "Content-type: text/html\r\n"
370             . "Link: <https://redir-hub.example.com/>; rel=\"hub\"\r\n"
371             . "Link: <http://example.com/redir-feed>; rel=\"self\"\r\n"
372             . "\r\n",
373             'http://example.org/redir-target'
374         );
375
376         $extractor = new phinde\HubUrlExtractor();
377         $extractor->setRequestTemplate(
378             new HTTP_Request2(null, null, ['adapter' => $mock])
379         );
380
381         $this->assertEquals(
382             [
383                 'hub'  => ['https://hub.example.com/'],
384                 'self' => 'http://example.com/feed',
385             ],
386             $extractor->getUrls('http://example.org/')
387         );
388     }
389
390     public function testGetUrlsHEADLinksForRedirectNone()
391     {
392         $mock = new HTTP_Request2_Adapter_Mock();
393         $this->addResponse(
394             $mock,
395             "HTTP/1.0 307 Temporary Redirect\r\n"
396             . "Content-type: text/html\r\n"
397             . "Location: http://example.org/redir-target\r\n"
398             . "\r\n",
399             'http://example.org/'
400         );
401         $this->addResponse(
402             $mock,
403             "HTTP/1.0 200 OK\r\n"
404             . "Content-type: text/html\r\n"
405             . "Link: <https://redir-hub.example.com/>; rel=\"hub\"\r\n"
406             . "Link: <http://example.com/redir-feed>; rel=\"self\"\r\n"
407             . "\r\n",
408             'http://example.org/redir-target'
409         );
410
411         $extractor = new phinde\HubUrlExtractor();
412         $extractor->setRequestTemplate(
413             new HTTP_Request2(null, null, ['adapter' => $mock])
414         );
415
416         $this->assertEquals(
417             [
418                 'hub'  => ['https://redir-hub.example.com/'],
419                 'self' => 'http://example.com/redir-feed',
420             ],
421             $extractor->getUrls('http://example.org/')
422         );
423     }
424 }
425 ?>