twitter-text-kow 1.3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,858 @@
1
+ # Copyright 2018 Twitter, Inc.
2
+ # Licensed under the Apache License, Version 2.0
3
+ # http://www.apache.org/licenses/LICENSE-2.0
4
+
5
+ # encoding: utf-8
6
+ require File.dirname(__FILE__) + '/spec_helper'
7
+
8
+ class TestAutolink
9
+ include Twitter::TwitterText::Autolink
10
+ end
11
+
12
+ describe Twitter::TwitterText::Autolink do
13
+ def original_text; end
14
+ def url; end
15
+
16
+ describe "auto_link_custom" do
17
+ before do
18
+ @autolinked_text = TestAutolink.new.auto_link(original_text) if original_text
19
+ end
20
+
21
+ describe "plain text" do
22
+ context "plain text with emoji" do
23
+ def original_text; "gotcha 👍"; end
24
+
25
+ it "should be unchanged" do
26
+ expect(@autolinked_text).to eq("gotcha 👍")
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "username autolinking" do
32
+ context "username preceded by a space" do
33
+ def original_text; "hello @jacob"; end
34
+
35
+ it "should be linked" do
36
+ expect(@autolinked_text).to link_to_screen_name('jacob')
37
+ end
38
+ end
39
+
40
+ context "username in camelCase" do
41
+ def original_text() "@jaCob iS cOoL" end
42
+
43
+ it "should be linked" do
44
+ expect(@autolinked_text).to link_to_screen_name('jaCob')
45
+ end
46
+ end
47
+
48
+ context "username at beginning of line" do
49
+ def original_text; "@jacob you're cool"; end
50
+
51
+ it "should be linked" do
52
+ expect(@autolinked_text).to link_to_screen_name('jacob')
53
+ end
54
+ end
55
+
56
+ context "username preceded by word character" do
57
+ def original_text; "meet@the beach"; end
58
+
59
+ it "should not be linked" do
60
+ expect(Nokogiri::HTML(@autolinked_text).search('a')).to be_empty
61
+ end
62
+ end
63
+
64
+ context "username preceded by non-word character" do
65
+ def original_text; "great.@jacob"; end
66
+
67
+ it "should be linked" do
68
+ expect(@autolinked_text).to link_to_screen_name('jacob')
69
+ end
70
+ end
71
+
72
+ context "username containing non-word characters" do
73
+ def original_text; "@zach&^$%^"; end
74
+
75
+ it "should not be linked" do
76
+ expect(@autolinked_text).to link_to_screen_name('zach')
77
+ end
78
+ end
79
+
80
+ context "username over twenty characters" do
81
+ def original_text
82
+ @twenty_character_username = "zach" * 5
83
+ "@" + @twenty_character_username + "1"
84
+ end
85
+
86
+ it "should not be linked" do
87
+ expect(@autolinked_text).to link_to_screen_name(@twenty_character_username)
88
+ end
89
+ end
90
+
91
+ context "username followed by japanese" do
92
+ def original_text; "@jacobの"; end
93
+
94
+ it "should be linked" do
95
+ expect(@autolinked_text).to link_to_screen_name('jacob')
96
+ end
97
+ end
98
+
99
+ context "username preceded by japanese" do
100
+ def original_text; "あ@matz"; end
101
+
102
+ it "should be linked" do
103
+ expect(@autolinked_text).to link_to_screen_name('matz')
104
+ end
105
+ end
106
+
107
+ context "username surrounded by japanese" do
108
+ def original_text; "あ@yoshimiの"; end
109
+
110
+ it "should be linked" do
111
+ expect(@autolinked_text).to link_to_screen_name('yoshimi')
112
+ end
113
+ end
114
+
115
+ context "username using full-width at-sign" do
116
+ def original_text
117
+ "#{[0xFF20].pack('U')}jacob"
118
+ end
119
+
120
+ it "should be linked" do
121
+ expect(@autolinked_text).to link_to_screen_name('jacob')
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "list path autolinking" do
127
+
128
+ context "when List is not available" do
129
+ it "should not be linked" do
130
+ @autolinked_text = TestAutolink.new.auto_link_usernames_or_lists("hello @jacob/my-list", :suppress_lists => true)
131
+ expect(@autolinked_text).to_not link_to_list_path('jacob/my-list')
132
+ expect(@autolinked_text).to include('my-list')
133
+ end
134
+ end
135
+
136
+ context "slug preceded by a space" do
137
+ def original_text; "hello @jacob/my-list"; end
138
+
139
+ it "should be linked" do
140
+ expect(@autolinked_text).to link_to_list_path('jacob/my-list')
141
+ end
142
+ end
143
+
144
+ context "username followed by a slash but no list" do
145
+ def original_text; "hello @jacob/ my-list"; end
146
+
147
+ it "should NOT be linked" do
148
+ expect(@autolinked_text).to_not link_to_list_path('jacob/my-list')
149
+ expect(@autolinked_text).to link_to_screen_name('jacob')
150
+ end
151
+ end
152
+
153
+ context "empty username followed by a list" do
154
+ def original_text; "hello @/my-list"; end
155
+
156
+ it "should NOT be linked" do
157
+ expect(Nokogiri::HTML(@autolinked_text).search('a')).to be_empty
158
+ end
159
+ end
160
+
161
+ context "list slug at beginning of line" do
162
+ def original_text; "@jacob/my-list"; end
163
+
164
+ it "should be linked" do
165
+ expect(@autolinked_text).to link_to_list_path('jacob/my-list')
166
+ end
167
+ end
168
+
169
+ context "username preceded by alpha-numeric character" do
170
+ def original_text; "meet@the/beach"; end
171
+
172
+ it "should not be linked" do
173
+ expect(Nokogiri::HTML(@autolinked_text).search('a')).to be_empty
174
+ end
175
+ end
176
+
177
+ context "username preceded by non-word character" do
178
+ def original_text; "great.@jacob/my-list"; end
179
+
180
+ it "should be linked" do
181
+ @autolinked_text = TestAutolink.new.auto_link("great.@jacob/my-list")
182
+ expect(@autolinked_text).to link_to_list_path('jacob/my-list')
183
+ end
184
+ end
185
+
186
+ context "username containing non-word characters" do
187
+ def original_text; "@zach/test&^$%^"; end
188
+
189
+ it "should be linked" do
190
+ expect(@autolinked_text).to link_to_list_path('zach/test')
191
+ end
192
+ end
193
+
194
+ context "username over twenty characters" do
195
+ def original_text
196
+ @twentyfive_character_list = "jack/" + ("a" * 25)
197
+ "@#{@twentyfive_character_list}12345"
198
+ end
199
+
200
+ it "should be linked" do
201
+ expect(@autolinked_text).to link_to_list_path(@twentyfive_character_list)
202
+ end
203
+ end
204
+ end
205
+
206
+ describe "hashtag autolinking" do
207
+ context "with an all numeric hashtag" do
208
+ def original_text; "#123"; end
209
+
210
+ it "should not be linked" do
211
+ expect(@autolinked_text).to_not have_autolinked_hashtag('#123')
212
+ end
213
+ end
214
+
215
+ context "with a hashtag with alphanumeric characters" do
216
+ def original_text; "#ab1d"; end
217
+
218
+ it "should be linked" do
219
+ expect(@autolinked_text).to have_autolinked_hashtag('#ab1d')
220
+ end
221
+ end
222
+
223
+ context "with a hashtag with underscores" do
224
+ def original_text; "#a_b_c_d"; end
225
+
226
+ it "should be linked" do
227
+ expect(@autolinked_text).to have_autolinked_hashtag(original_text)
228
+ end
229
+ end
230
+
231
+ context "with a hashtag that is preceded by a word character" do
232
+ def original_text; "ab#cd"; end
233
+
234
+ it "should not be linked" do
235
+ expect(@autolinked_text).to_not have_autolinked_hashtag(original_text)
236
+ end
237
+ end
238
+
239
+ context "with a page anchor in a url" do
240
+ def original_text; "Here's my url: http://foobar.com/#home"; end
241
+
242
+ it "should not link the hashtag" do
243
+ expect(@autolinked_text).to_not have_autolinked_hashtag('#home')
244
+ end
245
+
246
+ it "should link the url" do
247
+ expect(@autolinked_text).to have_autolinked_url('http://foobar.com/#home')
248
+ end
249
+ end
250
+
251
+ context "with a hashtag that starts with a number but has word characters" do
252
+ def original_text; "#2ab"; end
253
+
254
+ it "should be linked" do
255
+ expect(@autolinked_text).to have_autolinked_hashtag(original_text)
256
+ end
257
+ end
258
+
259
+ context "with multiple valid hashtags" do
260
+ def original_text; "I'm frickin' awesome #ab #cd #ef"; end
261
+
262
+ it "links each hashtag" do
263
+ expect(@autolinked_text).to have_autolinked_hashtag('#ab')
264
+ expect(@autolinked_text).to have_autolinked_hashtag('#cd')
265
+ expect(@autolinked_text).to have_autolinked_hashtag('#ef')
266
+ end
267
+ end
268
+
269
+ context "with a hashtag preceded by a ." do
270
+ def original_text; "ok, great.#abc"; end
271
+
272
+ it "should be linked" do
273
+ expect(@autolinked_text).to have_autolinked_hashtag('#abc')
274
+ end
275
+ end
276
+
277
+ context "with a hashtag preceded by a &" do
278
+ def original_text; "&#nbsp;"; end
279
+
280
+ it "should not be linked" do
281
+ expect(@autolinked_text).to_not have_autolinked_hashtag('#nbsp;')
282
+ end
283
+ end
284
+
285
+ context "with a hashtag that ends in an !" do
286
+ def original_text; "#great!"; end
287
+
288
+ it "should be linked, but should not include the !" do
289
+ expect(@autolinked_text).to have_autolinked_hashtag('#great')
290
+ end
291
+ end
292
+
293
+ context "with a hashtag followed by Japanese" do
294
+ def original_text; "#twj_devの"; end
295
+
296
+ it "should be linked" do
297
+ expect(@autolinked_text).to have_autolinked_hashtag('#twj_devの')
298
+ end
299
+ end
300
+
301
+ context "with a hashtag preceded by a full-width space" do
302
+ def original_text; "#{[0x3000].pack('U')}#twj_dev"; end
303
+
304
+ it "should be linked" do
305
+ expect(@autolinked_text).to have_autolinked_hashtag('#twj_dev')
306
+ end
307
+ end
308
+
309
+ context "with a hashtag followed by a full-width space" do
310
+ def original_text; "#twj_dev#{[0x3000].pack('U')}"; end
311
+
312
+ it "should be linked" do
313
+ expect(@autolinked_text).to have_autolinked_hashtag('#twj_dev')
314
+ end
315
+ end
316
+
317
+ context "with a hashtag using full-width hash" do
318
+ def original_text; "#{[0xFF03].pack('U')}twj_dev"; end
319
+
320
+ it "should be linked" do
321
+ link = Nokogiri::HTML(@autolinked_text).search('a')
322
+ expect((link.inner_text.respond_to?(:force_encoding) ? link.inner_text.force_encoding("utf-8") : link.inner_text)).to be == "#{[0xFF03].pack('U')}twj_dev"
323
+ expect(link.first['href']).to be == 'https://twitter.com/search?q=%23twj_dev'
324
+ end
325
+ end
326
+
327
+ context "with a hashtag containing an accented latin character" do
328
+ def original_text
329
+ # the hashtag is #éhashtag
330
+ "##{[0x00e9].pack('U')}hashtag"
331
+ end
332
+
333
+ it "should be linked" do
334
+ expect(@autolinked_text).to be == "<a class=\"tweet-url hashtag\" href=\"https://twitter.com/search?q=%23éhashtag\" rel=\"nofollow\" title=\"#éhashtag\">#éhashtag</a>"
335
+ end
336
+ end
337
+
338
+ end
339
+
340
+ describe "URL autolinking" do
341
+ def url; "http://www.google.com"; end
342
+
343
+ context "when embedded in plain text" do
344
+ def original_text; "On my search engine #{url} I found good links."; end
345
+
346
+ it "should be linked" do
347
+ expect(@autolinked_text).to have_autolinked_url(url)
348
+ end
349
+ end
350
+
351
+ context "when surrounded by Japanese;" do
352
+ def original_text; "いまなにしてる#{url}いまなにしてる"; end
353
+
354
+ it "should be linked" do
355
+ expect(@autolinked_text).to have_autolinked_url(url)
356
+ end
357
+ end
358
+
359
+ context "with a path surrounded by parentheses;" do
360
+ def original_text; "I found a neatness (#{url})"; end
361
+
362
+ it "should be linked" do
363
+ expect(@autolinked_text).to have_autolinked_url(url)
364
+ end
365
+
366
+ context "when the URL ends with a slash;" do
367
+ def url; "http://www.google.com/"; end
368
+
369
+ it "should be linked" do
370
+ expect(@autolinked_text).to have_autolinked_url(url)
371
+ end
372
+ end
373
+
374
+ context "when the URL has a path;" do
375
+ def url; "http://www.google.com/fsdfasdf"; end
376
+
377
+ it "should be linked" do
378
+ expect(@autolinked_text).to have_autolinked_url(url)
379
+ end
380
+ end
381
+ end
382
+
383
+ context "when path contains parens" do
384
+ def original_text; "I found a neatness (#{url})"; end
385
+
386
+ it "should be linked" do
387
+ expect(@autolinked_text).to have_autolinked_url(url)
388
+ end
389
+
390
+ context "wikipedia" do
391
+ def url; "http://en.wikipedia.org/wiki/Madonna_(artist)"; end
392
+
393
+ it "should be linked" do
394
+ expect(@autolinked_text).to have_autolinked_url(url)
395
+ end
396
+ end
397
+
398
+ context "IIS session" do
399
+ def url; "http://msdn.com/S(deadbeef)/page.htm"; end
400
+
401
+ it "should be linked" do
402
+ expect(@autolinked_text).to have_autolinked_url(url)
403
+ end
404
+ end
405
+
406
+ context "unbalanced parens" do
407
+ def url; "http://example.com/i_has_a_("; end
408
+
409
+ it "should be linked" do
410
+ expect(@autolinked_text).to have_autolinked_url("http://example.com/i_has_a_")
411
+ end
412
+ end
413
+
414
+ context "balanced parens with a double quote inside" do
415
+ def url; "http://foo.com/foo_(\")_bar" end
416
+
417
+ it "should be linked" do
418
+ expect(@autolinked_text).to have_autolinked_url("http://foo.com/foo_")
419
+ end
420
+ end
421
+
422
+ context "balanced parens hiding XSS" do
423
+ def url; 'http://x.xx.com/("style="color:red"onmouseover="alert(1)' end
424
+
425
+ it "should be linked" do
426
+ expect(@autolinked_text).to have_autolinked_url("http://x.xx.com/")
427
+ end
428
+ end
429
+ end
430
+
431
+ context "when preceded by a :" do
432
+ def original_text; "Check this out @hoverbird:#{url}"; end
433
+
434
+ it "should be linked" do
435
+ expect(@autolinked_text).to have_autolinked_url(url)
436
+ end
437
+ end
438
+
439
+ context "with a URL ending in allowed punctuation" do
440
+ it "does not consume ending punctuation" do
441
+ matcher = TestAutolink.new
442
+ %w| ? ! , . : ; ] ) } = \ ' |.each do |char|
443
+ expect(matcher.auto_link("#{url}#{char}")).to have_autolinked_url(url)
444
+ end
445
+ end
446
+ end
447
+
448
+ context "with a URL preceded in forbidden characters" do
449
+ it "should be linked" do
450
+ matcher = TestAutolink.new
451
+ %w| \ ' / ! = |.each do |char|
452
+ expect(matcher.auto_link("#{char}#{url}")).to have_autolinked_url(url)
453
+ end
454
+ end
455
+ end
456
+
457
+ context "when embedded in a link tag" do
458
+ def original_text; "<link rel='true'>#{url}</link>"; end
459
+
460
+ it "should be linked" do
461
+ expect(@autolinked_text).to have_autolinked_url(url)
462
+ end
463
+ end
464
+
465
+ context "with multiple URLs" do
466
+ def original_text; "http://www.links.org link at start of page, link at end http://www.foo.org"; end
467
+
468
+ it "should autolink each one" do
469
+ expect(@autolinked_text).to have_autolinked_url('http://www.links.org')
470
+ expect(@autolinked_text).to have_autolinked_url('http://www.foo.org')
471
+ end
472
+ end
473
+
474
+ context "with multiple URLs in different formats" do
475
+ def original_text; "http://foo.com https://bar.com http://mail.foobar.org"; end
476
+
477
+ it "should autolink each one, in the proper order" do
478
+ expect(@autolinked_text).to have_autolinked_url('http://foo.com')
479
+ expect(@autolinked_text).to have_autolinked_url('https://bar.com')
480
+ expect(@autolinked_text).to have_autolinked_url('http://mail.foobar.org')
481
+ end
482
+ end
483
+
484
+ context "with a URL having a long TLD" do
485
+ def original_text; "Yahoo integriert Facebook http://golem.mobi/0912/71607.html"; end
486
+
487
+ it "should autolink it" do
488
+ expect(@autolinked_text).to have_autolinked_url('http://golem.mobi/0912/71607.html')
489
+ end
490
+ end
491
+
492
+ context "with a url lacking the protocol" do
493
+ def original_text; "I like www.foobar.com dudes"; end
494
+
495
+ it "does not link at all" do
496
+ link = Nokogiri::HTML(@autolinked_text).search('a')
497
+ expect(link).to be_empty
498
+ end
499
+ end
500
+
501
+ context "with a @ in a URL" do
502
+ context "with XSS attack" do
503
+ def original_text; 'http://x.xx.com/@"style="color:pink"onmouseover=alert(1)//'; end
504
+
505
+ it "should not allow XSS follwing @" do
506
+ expect(@autolinked_text).to have_autolinked_url('http://x.xx.com/')
507
+ end
508
+ end
509
+
510
+ context "with a username not followed by a /" do
511
+ def original_text; 'http://example.com/@foobar'; end
512
+
513
+ it "should link url" do
514
+ expect(@autolinked_text).to have_autolinked_url('http://example.com/@foobar')
515
+ end
516
+ end
517
+
518
+ context "with a username followed by a /" do
519
+ def original_text; 'http://example.com/@foobar/'; end
520
+
521
+ it "should not link the username but link full url" do
522
+ expect(@autolinked_text).to have_autolinked_url('http://example.com/@foobar/')
523
+ expect(@autolinked_text).to_not link_to_screen_name('foobar')
524
+ end
525
+ end
526
+ end
527
+
528
+ context "regex engine quirks" do
529
+ context "does not spiral out of control on repeated periods" do
530
+ def original_text; "Test a ton of periods http://example.com/path.........................................."; end
531
+
532
+ it "should autolink" do
533
+ expect(@autolinked_text).to have_autolinked_url('http://example.com/path')
534
+ end
535
+ end
536
+
537
+ context "does not spiral out of control on repeated dashes" do
538
+ def original_text; "Single char file ext http://www.bestbuy.com/site/Currie+Technologies+-+Ezip+400+Scooter/9885188.p?id=1218189013070&skuId=9885188"; end
539
+
540
+ it "should autolink" do
541
+ expect(@autolinked_text).to have_autolinked_url('http://www.bestbuy.com/site/Currie+Technologies+-+Ezip+400+Scooter/9885188.p?id=1218189013070&skuId=9885188')
542
+ end
543
+ end
544
+ end
545
+
546
+ end
547
+
548
+ describe "Autolink all" do
549
+ before do
550
+ @linker = TestAutolink.new
551
+ end
552
+
553
+ it "should allow url/hashtag overlap" do
554
+ auto_linked = @linker.auto_link("https://twitter.com/#search")
555
+ expect(auto_linked).to have_autolinked_url('https://twitter.com/#search')
556
+ end
557
+
558
+ it "should not add invalid option in HTML tags" do
559
+ auto_linked = @linker.auto_link("https://twitter.com/ is a URL, not a hashtag", :hashtag_class => 'hashtag_classname')
560
+ expect(auto_linked).to have_autolinked_url('https://twitter.com/')
561
+ expect(auto_linked).to_not include('hashtag_class')
562
+ expect(auto_linked).to_not include('hashtag_classname')
563
+ end
564
+
565
+ it "should autolink url/hashtag/mention in text with Unicode supplementary characters" do
566
+ auto_linked = @linker.auto_link("#{[0x10400].pack('U')} #hashtag #{[0x10400].pack('U')} @mention #{[0x10400].pack('U')} http://twitter.com/")
567
+ expect(auto_linked).to have_autolinked_hashtag('#hashtag')
568
+ expect(auto_linked).to link_to_screen_name('mention')
569
+ expect(auto_linked).to have_autolinked_url('http://twitter.com/')
570
+ end
571
+ end
572
+
573
+ end
574
+
575
+ describe "autolinking options" do
576
+ before do
577
+ @linker = TestAutolink.new
578
+ end
579
+
580
+ it "should show display_url when :url_entities provided" do
581
+ linked = @linker.auto_link("http://t.co/0JG5Mcq", :url_entities => [{
582
+ "url" => "http://t.co/0JG5Mcq",
583
+ "display_url" => "blog.twitter.com/2011/05/twitte…",
584
+ "expanded_url" => "http://blog.twitter.com/2011/05/twitter-for-mac-update.html",
585
+ "indices" => [
586
+ 84,
587
+ 103
588
+ ]
589
+ }])
590
+ html = Nokogiri::HTML(linked)
591
+ expect(html.search('a')).to_not be_empty
592
+ expect(html.search('a[@href="http://t.co/0JG5Mcq"]')).to_not be_empty
593
+ expect(html.search('span[@class=js-display-url]').inner_text).to be == "blog.twitter.com/2011/05/twitte"
594
+ expect(html.inner_text).to be == " http://blog.twitter.com/2011/05/twitter-for-mac-update.html …"
595
+ expect(html.search('span[@style="position:absolute;left:-9999px;"]').size).to be == 4
596
+ end
597
+
598
+ it "should accept invisible_tag_attrs option" do
599
+ linked = @linker.auto_link("http://t.co/0JG5Mcq",
600
+ {
601
+ :url_entities => [{
602
+ "url" => "http://t.co/0JG5Mcq",
603
+ "display_url" => "blog.twitter.com/2011/05/twitte…",
604
+ "expanded_url" => "http://blog.twitter.com/2011/05/twitter-for-mac-update.html",
605
+ "indices" => [
606
+ 0,
607
+ 19
608
+ ]
609
+ }],
610
+ :invisible_tag_attrs => "style='dummy;'"
611
+ })
612
+ html = Nokogiri::HTML(linked)
613
+ expect(html.search('span[@style="dummy;"]').size).to be == 4
614
+ end
615
+
616
+ it "should show display_url if available in entity" do
617
+ linked = @linker.auto_link_entities("http://t.co/0JG5Mcq",
618
+ [{
619
+ :url => "http://t.co/0JG5Mcq",
620
+ :display_url => "blog.twitter.com/2011/05/twitte…",
621
+ :expanded_url => "http://blog.twitter.com/2011/05/twitter-for-mac-update.html",
622
+ :indices => [0, 19]
623
+ }]
624
+ )
625
+ html = Nokogiri::HTML(linked)
626
+ expect(html.search('a')).to_not be_empty
627
+ expect(html.search('a[@href="http://t.co/0JG5Mcq"]')).to_not be_empty
628
+ expect(html.search('span[@class=js-display-url]').inner_text).to be == "blog.twitter.com/2011/05/twitte"
629
+ expect(html.inner_text).to be == " http://blog.twitter.com/2011/05/twitter-for-mac-update.html …"
630
+ end
631
+
632
+ it "should apply :class as a CSS class" do
633
+ linked = @linker.auto_link("http://example.com/", :class => 'myclass')
634
+ expect(linked).to have_autolinked_url('http://example.com/')
635
+ expect(linked).to match(/myclass/)
636
+ end
637
+
638
+ it "should apply :url_class only on URL" do
639
+ linked = @linker.auto_link("http://twitter.com")
640
+ expect(linked).to have_autolinked_url('http://twitter.com')
641
+ expect(expect(linked)).to_not match(/class/)
642
+
643
+ linked = @linker.auto_link("http://twitter.com", :url_class => 'testClass')
644
+ expect(linked).to have_autolinked_url('http://twitter.com')
645
+ expect(linked).to match(/class=\"testClass\"/)
646
+
647
+ linked = @linker.auto_link("#hash @tw", :url_class => 'testClass')
648
+ expect(linked).to match(/class=\"tweet-url hashtag\"/)
649
+ expect(linked).to match(/class=\"tweet-url username\"/)
650
+ expect(linked).to_not match(/class=\"testClass\"/)
651
+ end
652
+
653
+ it "should add rel=nofollow by default" do
654
+ linked = @linker.auto_link("http://example.com/")
655
+ expect(linked).to have_autolinked_url('http://example.com/')
656
+ expect(linked).to match(/nofollow/)
657
+ end
658
+
659
+ it "should include the '@' symbol in a username when passed :username_include_symbol" do
660
+ linked = @linker.auto_link("@user", :username_include_symbol => true)
661
+ expect(linked).to link_to_screen_name('user', '@user')
662
+ end
663
+
664
+ it "should include the '@' symbol in a list when passed :username_include_symbol" do
665
+ linked = @linker.auto_link("@user/list", :username_include_symbol => true)
666
+ expect(linked).to link_to_list_path('user/list', '@user/list')
667
+ end
668
+
669
+ it "should not add rel=nofollow when passed :suppress_no_follow" do
670
+ linked = @linker.auto_link("http://example.com/", :suppress_no_follow => true)
671
+ expect(linked).to have_autolinked_url('http://example.com/')
672
+ expect(linked).to_not match(/nofollow/)
673
+ end
674
+
675
+ it "should not add a target attribute by default" do
676
+ linked = @linker.auto_link("http://example.com/")
677
+ expect(linked).to have_autolinked_url('http://example.com/')
678
+ expect(linked).to_not match(/target=/)
679
+ end
680
+
681
+ it "should respect the :target option" do
682
+ linked = @linker.auto_link("http://example.com/", :target => 'mywindow')
683
+ expect(linked).to have_autolinked_url('http://example.com/')
684
+ expect(linked).to match(/target="mywindow"/)
685
+ end
686
+
687
+ it "should customize href by username_url_block option" do
688
+ linked = @linker.auto_link("@test", :username_url_block => lambda{|a| "dummy"})
689
+ expect(linked).to have_autolinked_url('dummy', 'test')
690
+ end
691
+
692
+ it "should customize href by list_url_block option" do
693
+ linked = @linker.auto_link("@test/list", :list_url_block => lambda{|a| "dummy"})
694
+ expect(linked).to have_autolinked_url('dummy', 'test/list')
695
+ end
696
+
697
+ it "should customize href by hashtag_url_block option" do
698
+ linked = @linker.auto_link("#hashtag", :hashtag_url_block => lambda{|a| "dummy"})
699
+ expect(linked).to have_autolinked_url('dummy', '#hashtag')
700
+ end
701
+
702
+ it "should customize href by cashtag_url_block option" do
703
+ linked = @linker.auto_link("$CASH", :cashtag_url_block => lambda{|a| "dummy"})
704
+ expect(linked).to have_autolinked_url('dummy', '$CASH')
705
+ end
706
+
707
+ it "should customize href by link_url_block option" do
708
+ linked = @linker.auto_link("http://example.com/", :link_url_block => lambda{|a| "dummy"})
709
+ expect(linked).to have_autolinked_url('dummy', 'http://example.com/')
710
+ end
711
+
712
+ it "should modify link attributes by link_attribute_block" do
713
+ linked = @linker.auto_link("#hash @mention",
714
+ :link_attribute_block => lambda{|entity, attributes|
715
+ attributes[:"dummy-hash-attr"] = "test" if entity[:hashtag]
716
+ }
717
+ )
718
+ expect(linked).to match(/<a[^>]+hashtag[^>]+dummy-hash-attr=\"test\"[^>]+>/)
719
+ expect(linked).to_not match(/<a[^>]+username[^>]+dummy-hash-attr=\"test\"[^>]+>/)
720
+ expect(linked).to_not match(/link_attribute_block/i)
721
+
722
+ linked = @linker.auto_link("@mention http://twitter.com/",
723
+ :link_attribute_block => lambda{|entity, attributes|
724
+ attributes["dummy-url-attr"] = entity[:url] if entity[:url]
725
+ }
726
+ )
727
+ expect(linked).to_not match(/<a[^>]+username[^>]+dummy-url-attr=\"http:\/\/twitter.com\/\"[^>]*>/)
728
+ expect(linked).to match(/<a[^>]+dummy-url-attr=\"http:\/\/twitter.com\/\"/)
729
+ end
730
+
731
+ it "should modify link text by link_text_block" do
732
+ linked = @linker.auto_link("#hash @mention",
733
+ :link_text_block => lambda{|entity, text|
734
+ entity[:hashtag] ? "#replaced" : "pre_#{text}_post"
735
+ }
736
+ )
737
+ expect(linked).to match(/<a[^>]+>#replaced<\/a>/)
738
+ expect(linked).to match(/<a[^>]+>pre_mention_post<\/a>/)
739
+
740
+ linked = @linker.auto_link("#hash @mention", {
741
+ :link_text_block => lambda{|entity, text|
742
+ "pre_#{text}_post"
743
+ },
744
+ :symbol_tag => "s", :text_with_symbol_tag => "b", :username_include_symbol => true
745
+ })
746
+ expect(linked).to match(/<a[^>]+>pre_<s>#<\/s><b>hash<\/b>_post<\/a>/)
747
+ expect(linked).to match(/<a[^>]+>pre_<s>@<\/s><b>mention<\/b>_post<\/a>/)
748
+ end
749
+
750
+ it "should apply :url_target only to auto-linked URLs" do
751
+ auto_linked = @linker.auto_link("#hashtag @mention http://test.com/", {:url_target => '_blank'})
752
+ expect(auto_linked).to have_autolinked_hashtag('#hashtag')
753
+ expect(auto_linked).to link_to_screen_name('mention')
754
+ expect(auto_linked).to have_autolinked_url('http://test.com/')
755
+ expect(auto_linked).to_not match(/<a[^>]+hashtag[^>]+target[^>]+>/)
756
+ expect(auto_linked).to_not match(/<a[^>]+username[^>]+target[^>]+>/)
757
+ expect(auto_linked).to match(/<a[^>]+test.com[^>]+target=\"_blank\"[^>]*>/)
758
+ end
759
+
760
+ it "should apply target='_blank' only to auto-linked URLs when :target_blank is set to true" do
761
+ auto_linked = @linker.auto_link("#hashtag @mention http://test.com/", {:target_blank => true})
762
+ expect(auto_linked).to have_autolinked_hashtag('#hashtag')
763
+ expect(auto_linked).to link_to_screen_name('mention')
764
+ expect(auto_linked).to have_autolinked_url('http://test.com/')
765
+ expect(auto_linked).to match(/<a[^>]+hashtag[^>]+target=\"_blank\"[^>]*>/)
766
+ expect(auto_linked).to match(/<a[^>]+username[^>]+target=\"_blank\"[^>]*>/)
767
+ expect(auto_linked).to match(/<a[^>]+test.com[^>]+target=\"_blank\"[^>]*>/)
768
+ end
769
+ end
770
+
771
+ describe "link_url_with_entity" do
772
+ before do
773
+ @linker = TestAutolink.new
774
+ end
775
+
776
+ it "should use display_url and expanded_url" do
777
+ expect(@linker.send(:link_url_with_entity,
778
+ {
779
+ :url => "http://t.co/abcde",
780
+ :display_url => "twitter.com",
781
+ :expanded_url => "http://twitter.com/"},
782
+ {:invisible_tag_attrs => "class='invisible'"}).gsub('"', "'")).to be == "<span class='tco-ellipsis'><span class='invisible'>&nbsp;</span></span><span class='invisible'>http://</span><span class='js-display-url'>twitter.com</span><span class='invisible'>/</span><span class='tco-ellipsis'><span class='invisible'>&nbsp;</span></span>";
783
+ end
784
+
785
+ it "should correctly handle display_url ending with '…'" do
786
+ expect(@linker.send(:link_url_with_entity,
787
+ {
788
+ :url => "http://t.co/abcde",
789
+ :display_url => "twitter.com…",
790
+ :expanded_url => "http://twitter.com/abcdefg"},
791
+ {:invisible_tag_attrs => "class='invisible'"}).gsub('"', "'")).to be == "<span class='tco-ellipsis'><span class='invisible'>&nbsp;</span></span><span class='invisible'>http://</span><span class='js-display-url'>twitter.com</span><span class='invisible'>/abcdefg</span><span class='tco-ellipsis'><span class='invisible'>&nbsp;</span>…</span>";
792
+ end
793
+
794
+ it "should correctly handle display_url starting with '…'" do
795
+ expect(@linker.send(:link_url_with_entity,
796
+ {
797
+ :url => "http://t.co/abcde",
798
+ :display_url => "…tter.com/abcdefg",
799
+ :expanded_url => "http://twitter.com/abcdefg"},
800
+ {:invisible_tag_attrs => "class='invisible'"}).gsub('"', "'")).to be == "<span class='tco-ellipsis'>…<span class='invisible'>&nbsp;</span></span><span class='invisible'>http://twi</span><span class='js-display-url'>tter.com/abcdefg</span><span class='invisible'></span><span class='tco-ellipsis'><span class='invisible'>&nbsp;</span></span>";
801
+ end
802
+
803
+ it "should not create spans if display_url and expanded_url are on different domains" do
804
+ expect(@linker.send(:link_url_with_entity,
805
+ {
806
+ :url => "http://t.co/abcde",
807
+ :display_url => "pic.twitter.com/xyz",
808
+ :expanded_url => "http://twitter.com/foo/statuses/123/photo/1"},
809
+ {:invisible_tag_attrs => "class='invisible'"}).gsub('"', "'")).to be == "pic.twitter.com/xyz"
810
+ end
811
+ end
812
+
813
+ describe "symbol_tag" do
814
+ before do
815
+ @linker = TestAutolink.new
816
+ end
817
+ it "should put :symbol_tag around symbol" do
818
+ expect(@linker.auto_link("@mention", {:symbol_tag => 's', :username_include_symbol=>true})).to match(/<s>@<\/s>mention/)
819
+ expect(@linker.auto_link("#hash", {:symbol_tag => 's'})).to match(/<s>#<\/s>hash/)
820
+ result = @linker.auto_link("@mention #hash $CASH", {:symbol_tag => 'b', :username_include_symbol=>true})
821
+ expect(result).to match(/<b>@<\/b>mention/)
822
+ expect(result).to match(/<b>#<\/b>hash/)
823
+ expect(result).to match(/<b>\$<\/b>CASH/)
824
+ end
825
+ it "should put :text_with_symbol_tag around text" do
826
+ result = @linker.auto_link("@mention #hash $CASH", {:text_with_symbol_tag => 'b'})
827
+ expect(result).to match(/<b>mention<\/b>/)
828
+ expect(result).to match(/<b>hash<\/b>/)
829
+ expect(result).to match(/<b>CASH<\/b>/)
830
+ end
831
+ it "should put :symbol_tag around symbol and :text_with_symbol_tag around text" do
832
+ result = @linker.auto_link("@mention #hash $CASH", {:symbol_tag => 's', :text_with_symbol_tag => 'b', :username_include_symbol=>true})
833
+ expect(result).to match(/<s>@<\/s><b>mention<\/b>/)
834
+ expect(result).to match(/<s>#<\/s><b>hash<\/b>/)
835
+ expect(result).to match(/<s>\$<\/s><b>CASH<\/b>/)
836
+ end
837
+ end
838
+
839
+ describe "html_escape" do
840
+ before do
841
+ @linker = TestAutolink.new
842
+ end
843
+ it "should escape html entities properly" do
844
+ expect(@linker.html_escape("&")).to be == "&amp;"
845
+ expect(@linker.html_escape(">")).to be == "&gt;"
846
+ expect(@linker.html_escape("<")).to be == "&lt;"
847
+ expect(@linker.html_escape("\"")).to be == "&quot;"
848
+ expect(@linker.html_escape("'")).to be == "&#39;"
849
+ expect(@linker.html_escape("&<>\"")).to be == "&amp;&lt;&gt;&quot;"
850
+ expect(@linker.html_escape("<div>")).to be == "&lt;div&gt;"
851
+ expect(@linker.html_escape("a&b")).to be == "a&amp;b"
852
+ expect(@linker.html_escape("<a href=\"https://twitter.com\" target=\"_blank\">twitter & friends</a>")).to be == "&lt;a href=&quot;https://twitter.com&quot; target=&quot;_blank&quot;&gt;twitter &amp; friends&lt;/a&gt;"
853
+ expect(@linker.html_escape("&amp;")).to be == "&amp;amp;"
854
+ expect(@linker.html_escape(nil)).to be == nil
855
+ end
856
+ end
857
+
858
+ end