ritter 0.0.87 → 0.0.88

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