aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/bookmark/LinkUtilsTest.php
blob: 1b8688e6d398fc1381e6b2acc586ae2562c282f2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
<?php

namespace Shaarli\Bookmark;

use ReferenceLinkDB;

require_once 'tests/utils/CurlUtils.php';

/**
 * Class LinkUtilsTest.
 */
class LinkUtilsTest extends \PHPUnit\Framework\TestCase
{
    /**
     * Test html_extract_title() when the title is found.
     */
    public function testHtmlExtractExistentTitle()
    {
        $title = 'Read me please.';
        $html = '<html><meta>stuff</meta><title>' . $title . '</title></html>';
        $this->assertEquals($title, html_extract_title($html));
        $html = '<html><title>' . $title . '</title>blabla<title>another</title></html>';
        $this->assertEquals($title, html_extract_title($html));
    }

    /**
     * Test html_extract_title() when the title is not found.
     */
    public function testHtmlExtractNonExistentTitle()
    {
        $html = '<html><meta>stuff</meta></html>';
        $this->assertFalse(html_extract_title($html));
    }

    /**
     * Test headers_extract_charset() when the charset is found.
     */
    public function testHeadersExtractExistentCharset()
    {
        $charset = 'x-MacCroatian';
        $headers = 'text/html; charset=' . $charset;
        $this->assertEquals(strtolower($charset), header_extract_charset($headers));
    }

    /**
     * Test headers_extract_charset() when the charset is not found.
     */
    public function testHeadersExtractNonExistentCharset()
    {
        $headers = '';
        $this->assertFalse(header_extract_charset($headers));

        $headers = 'text/html';
        $this->assertFalse(header_extract_charset($headers));
    }

    /**
     * Test html_extract_charset() when the charset is found.
     */
    public function testHtmlExtractExistentCharset()
    {
        $charset = 'x-MacCroatian';
        $html = '<html><meta>stuff2</meta><meta charset="' . $charset . '"/></html>';
        $this->assertEquals(strtolower($charset), html_extract_charset($html));
    }

    /**
     * Test html_extract_charset() when the charset is not found.
     */
    public function testHtmlExtractNonExistentCharset()
    {
        $html = '<html><meta>stuff</meta></html>';
        $this->assertFalse(html_extract_charset($html));
        $html = '<html><meta>stuff</meta><meta charset=""/></html>';
        $this->assertFalse(html_extract_charset($html));
    }

    /**
     * Test the download callback with valid value
     */
    public function testCurlDownloadCallbackOk()
    {
        $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_ok');
        $data = [
            'HTTP/1.1 200 OK',
            'Server: GitHub.com',
            'Date: Sat, 28 Oct 2017 12:01:33 GMT',
            'Content-Type: text/html; charset=utf-8',
            'Status: 200 OK',
            'end' => 'th=device-width">'
                . '<title>Refactoring · GitHub</title>'
                . '<link rel="search" type="application/opensea',
            '<title>ignored</title>',
        ];
        foreach ($data as $key => $line) {
            $ignore = null;
            $expected = $key !== 'end' ? strlen($line) : false;
            $this->assertEquals($expected, $callback($ignore, $line));
            if ($expected === false) {
                break;
            }
        }
        $this->assertEquals('utf-8', $charset);
        $this->assertEquals('Refactoring · GitHub', $title);
    }

    /**
     * Test the download callback with valid values and no charset
     */
    public function testCurlDownloadCallbackOkNoCharset()
    {
        $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_no_charset');
        $data = [
            'HTTP/1.1 200 OK',
            'end' => 'th=device-width">'
                . '<title>Refactoring · GitHub</title>'
                . '<link rel="search" type="application/opensea',
            '<title>ignored</title>',
        ];
        foreach ($data as $key => $line) {
            $ignore = null;
            $this->assertEquals(strlen($line), $callback($ignore, $line));
        }
        $this->assertEmpty($charset);
        $this->assertEquals('Refactoring · GitHub', $title);
    }

    /**
     * Test the download callback with valid values and no charset
     */
    public function testCurlDownloadCallbackOkHtmlCharset()
    {
        $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_no_charset');
        $data = [
            'HTTP/1.1 200 OK',
            '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
            'end' => 'th=device-width">'
                . '<title>Refactoring · GitHub</title>'
                . '<link rel="search" type="application/opensea',
            '<title>ignored</title>',
        ];
        foreach ($data as $key => $line) {
            $ignore = null;
            $expected = $key !== 'end' ? strlen($line) : false;
            $this->assertEquals($expected, $callback($ignore, $line));
            if ($expected === false) {
                break;
            }
        }
        $this->assertEquals('utf-8', $charset);
        $this->assertEquals('Refactoring · GitHub', $title);
    }

    /**
     * Test the download callback with valid values and no title
     */
    public function testCurlDownloadCallbackOkNoTitle()
    {
        $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_ok');
        $data = [
            'HTTP/1.1 200 OK',
            'end' => 'th=device-width">Refactoring · GitHub<link rel="search" type="application/opensea',
            'ignored',
        ];
        foreach ($data as $key => $line) {
            $ignore = null;
            $this->assertEquals(strlen($line), $callback($ignore, $line));
        }
        $this->assertEquals('utf-8', $charset);
        $this->assertEmpty($title);
    }

    /**
     * Test the download callback with an invalid content type.
     */
    public function testCurlDownloadCallbackInvalidContentType()
    {
        $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_ct_ko');
        $ignore = null;
        $this->assertFalse($callback($ignore, ''));
        $this->assertEmpty($charset);
        $this->assertEmpty($title);
    }

    /**
     * Test the download callback with an invalid response code.
     */
    public function testCurlDownloadCallbackInvalidResponseCode()
    {
        $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_rc_ko');
        $ignore = null;
        $this->assertFalse($callback($ignore, ''));
        $this->assertEmpty($charset);
        $this->assertEmpty($title);
    }

    /**
     * Test the download callback with an invalid content type and response code.
     */
    public function testCurlDownloadCallbackInvalidContentTypeAndResponseCode()
    {
        $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_rs_ct_ko');
        $ignore = null;
        $this->assertFalse($callback($ignore, ''));
        $this->assertEmpty($charset);
        $this->assertEmpty($title);
    }

    /**
     * Test count_private.
     */
    public function testCountPrivateLinks()
    {
        $refDB = new ReferenceLinkDB();
        $this->assertEquals($refDB->countPrivateLinks(), count_private($refDB->getLinks()));
    }

    /**
     * Test text2clickable without a redirector being set.
     */
    public function testText2clickableWithoutRedirector()
    {
        $text = 'stuff http://hello.there/is=someone#here otherstuff';
        $expectedText = 'stuff <a href="http://hello.there/is=someone#here">'
            . 'http://hello.there/is=someone#here</a> otherstuff';
        $processedText = text2clickable($text, '');
        $this->assertEquals($expectedText, $processedText);

        $text = 'stuff http://hello.there/is=someone#here(please) otherstuff';
        $expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)">'
            . 'http://hello.there/is=someone#here(please)</a> otherstuff';
        $processedText = text2clickable($text, '');
        $this->assertEquals($expectedText, $processedText);

        $text = 'stuff http://hello.there/is=someone#here(please)&no otherstuff';
        $expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)&no">'
            . 'http://hello.there/is=someone#here(please)&no</a> otherstuff';
        $processedText = text2clickable($text, '');
        $this->assertEquals($expectedText, $processedText);
    }

    /**
     * Test text2clickable with a redirector set.
     */
    public function testText2clickableWithRedirector()
    {
        $text = 'stuff http://hello.there/is=someone#here otherstuff';
        $redirector = 'http://redirector.to';
        $expectedText = 'stuff <a href="' .
            $redirector .
            urlencode('http://hello.there/is=someone#here') .
            '">http://hello.there/is=someone#here</a> otherstuff';
        $processedText = text2clickable($text, $redirector);
        $this->assertEquals($expectedText, $processedText);
    }

    /**
     * Test text2clickable a redirector set and without URL encode.
     */
    public function testText2clickableWithRedirectorDontEncode()
    {
        $text = 'stuff http://hello.there/?is=someone&or=something#here otherstuff';
        $redirector = 'http://redirector.to';
        $expectedText = 'stuff <a href="' .
            $redirector .
            'http://hello.there/?is=someone&or=something#here' .
            '">http://hello.there/?is=someone&or=something#here</a> otherstuff';
        $processedText = text2clickable($text, $redirector, false);
        $this->assertEquals($expectedText, $processedText);
    }

    /**
     * Test testSpace2nbsp.
     */
    public function testSpace2nbsp()
    {
        $text = '  Are you   thrilled  by flags   ?' . PHP_EOL . ' Really?';
        $expectedText = '&nbsp; Are you &nbsp; thrilled &nbsp;by flags &nbsp; ?' . PHP_EOL . '&nbsp;Really?';
        $processedText = space2nbsp($text);
        $this->assertEquals($expectedText, $processedText);
    }

    /**
     * Test hashtags auto-link.
     */
    public function testHashtagAutolink()
    {
        $index = 'http://domain.tld/';
        $rawDescription = '#hashtag\n
            # nothashtag\n
            test#nothashtag #hashtag \#nothashtag\n
            test #hashtag #hashtag test #hashtag.test\n
            #hashtag #hashtag-nothashtag #hashtag_hashtag\n
            What is #ашок anyway?\n
            カタカナ #カタカナ」カタカナ\n';
        $autolinkedDescription = hashtag_autolink($rawDescription, $index);

        $this->assertContains($this->getHashtagLink('hashtag', $index), $autolinkedDescription);
        $this->assertNotContains(' #hashtag', $autolinkedDescription);
        $this->assertNotContains('>#nothashtag', $autolinkedDescription);
        $this->assertContains($this->getHashtagLink('ашок', $index), $autolinkedDescription);
        $this->assertContains($this->getHashtagLink('カタカナ', $index), $autolinkedDescription);
        $this->assertContains($this->getHashtagLink('hashtag_hashtag', $index), $autolinkedDescription);
        $this->assertNotContains($this->getHashtagLink('hashtag-nothashtag', $index), $autolinkedDescription);
    }

    /**
     * Test hashtags auto-link without index URL.
     */
    public function testHashtagAutolinkNoIndex()
    {
        $rawDescription = 'blabla #hashtag x#nothashtag';
        $autolinkedDescription = hashtag_autolink($rawDescription);

        $this->assertContains($this->getHashtagLink('hashtag'), $autolinkedDescription);
        $this->assertNotContains(' #hashtag', $autolinkedDescription);
        $this->assertNotContains('>#nothashtag', $autolinkedDescription);
    }

    /**
     * Util function to build an hashtag link.
     *
     * @param string $hashtag Hashtag name.
     * @param string $index Index URL.
     *
     * @return string HTML hashtag link.
     */
    private function getHashtagLink($hashtag, $index = '')
    {
        $hashtagLink = '<a href="' . $index . '?addtag=$1" title="Hashtag $1">#$1</a>';
        return str_replace('$1', $hashtag, $hashtagLink);
    }
}