ritter 0.0.87 → 0.0.88
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/.gemtest +0 -0
- data/.gitignore +40 -0
- data/.gitmodules +3 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE +188 -0
- data/README.rdoc +112 -0
- data/Rakefile +64 -0
- data/lib/twitter-text/autolink.rb +443 -0
- data/lib/twitter-text/deprecation.rb +15 -0
- data/lib/twitter-text/extractor.rb +328 -0
- data/lib/twitter-text/hash_helper.rb +21 -0
- data/lib/twitter-text/hit_highlighter.rb +86 -0
- data/lib/twitter-text/regex.rb +366 -0
- data/lib/twitter-text/rewriter.rb +59 -0
- data/lib/twitter-text/unicode.rb +26 -0
- data/lib/twitter-text/validation.rb +113 -0
- data/lib/twitter-text.rb +22 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/autolinking_spec.rb +826 -0
- data/spec/extractor_spec.rb +368 -0
- data/spec/hithighlighter_spec.rb +92 -0
- data/spec/regex_spec.rb +38 -0
- data/spec/rewriter_spec.rb +548 -0
- data/spec/spec_helper.rb +127 -0
- data/spec/test_urls.rb +80 -0
- data/spec/twitter_text_spec.rb +21 -0
- data/spec/unicode_spec.rb +31 -0
- data/spec/validation_spec.rb +43 -0
- data/test/conformance_test.rb +182 -0
- data/twitter-text.gemspec +29 -0
- metadata +42 -8
@@ -0,0 +1,548 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
3
|
+
|
4
|
+
describe Twitter::Rewriter do
|
5
|
+
def original_text; end
|
6
|
+
def url; end
|
7
|
+
|
8
|
+
def block(*args)
|
9
|
+
if Array === @block_args
|
10
|
+
unless Array === @block_args.first
|
11
|
+
@block_args = [@block_args]
|
12
|
+
end
|
13
|
+
@block_args << args
|
14
|
+
else
|
15
|
+
@block_args = args
|
16
|
+
end
|
17
|
+
"[rewritten]"
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "rewrite usernames" do #{{{
|
21
|
+
before do
|
22
|
+
@rewritten_text = Twitter::Rewriter.rewrite_usernames_or_lists(original_text, &method(:block))
|
23
|
+
end
|
24
|
+
|
25
|
+
context "username preceded by a space" do
|
26
|
+
def original_text; "hello @jacob"; end
|
27
|
+
|
28
|
+
it "should be rewritten" do
|
29
|
+
@block_args.should == ["@", "jacob", nil]
|
30
|
+
@rewritten_text.should == "hello [rewritten]"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "username at beginning of line" do
|
35
|
+
def original_text; "@jacob you're cool"; end
|
36
|
+
|
37
|
+
it "should be rewritten" do
|
38
|
+
@block_args.should == ["@", "jacob", nil]
|
39
|
+
@rewritten_text.should == "[rewritten] you're cool"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "username preceded by word character" do
|
44
|
+
def original_text; "meet@the beach"; end
|
45
|
+
|
46
|
+
it "should not be rewritten" do
|
47
|
+
@block_args.should be_nil
|
48
|
+
@rewritten_text.should == "meet@the beach"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "username preceded by non-word character" do
|
53
|
+
def original_text; "great.@jacob"; end
|
54
|
+
|
55
|
+
it "should be rewritten" do
|
56
|
+
@block_args.should == ["@", "jacob", nil]
|
57
|
+
@rewritten_text.should == "great.[rewritten]"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "username containing non-word characters" do
|
62
|
+
def original_text; "@jacob&^$%^"; end
|
63
|
+
|
64
|
+
it "should be rewritten" do
|
65
|
+
@block_args.should == ["@", "jacob", nil]
|
66
|
+
@rewritten_text.should == "[rewritten]&^$%^"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "username over twenty characters" do
|
71
|
+
def original_text
|
72
|
+
@twenty_character_username = "zach" * 5
|
73
|
+
"@" + @twenty_character_username + "1"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should be rewritten" do
|
77
|
+
@block_args.should == ["@", @twenty_character_username, nil]
|
78
|
+
@rewritten_text.should == "[rewritten]1"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "username followed by japanese" do
|
83
|
+
def original_text; "@jacobの"; end
|
84
|
+
|
85
|
+
it "should be rewritten" do
|
86
|
+
@block_args.should == ["@", "jacob", nil]
|
87
|
+
@rewritten_text.should == "[rewritten]の"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "username preceded by japanese" do
|
92
|
+
def original_text; "あ@jacob"; end
|
93
|
+
|
94
|
+
it "should be rewritten" do
|
95
|
+
@block_args.should == ["@", "jacob", nil]
|
96
|
+
@rewritten_text.should == "あ[rewritten]"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "username surrounded by japanese" do
|
101
|
+
def original_text; "あ@jacobの"; end
|
102
|
+
|
103
|
+
it "should be rewritten" do
|
104
|
+
@block_args.should == ["@", "jacob", nil]
|
105
|
+
@rewritten_text.should == "あ[rewritten]の"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "username using full-width at-sign" do
|
110
|
+
def original_text
|
111
|
+
"#{[0xFF20].pack('U')}jacob"
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should be rewritten" do
|
115
|
+
@block_args.should == ["@", "jacob", nil]
|
116
|
+
@rewritten_text.should == "[rewritten]"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end #}}}
|
120
|
+
|
121
|
+
describe "rewrite lists" do #{{{
|
122
|
+
before do
|
123
|
+
@rewritten_text = Twitter::Rewriter.rewrite_usernames_or_lists(original_text, &method(:block))
|
124
|
+
end
|
125
|
+
|
126
|
+
context "slug preceded by a space" do
|
127
|
+
def original_text; "hello @jacob/my-list"; end
|
128
|
+
|
129
|
+
it "should be rewritten" do
|
130
|
+
@block_args.should == ["@", "jacob", "/my-list"]
|
131
|
+
@rewritten_text.should == "hello [rewritten]"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "username followed by a slash but no list" do
|
136
|
+
def original_text; "hello @jacob/ my-list"; end
|
137
|
+
|
138
|
+
it "should not be rewritten" do
|
139
|
+
@block_args.should == ["@", "jacob", nil]
|
140
|
+
@rewritten_text.should == "hello [rewritten]/ my-list"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context "empty username followed by a list" do
|
145
|
+
def original_text; "hello @/my-list"; end
|
146
|
+
|
147
|
+
it "should not be rewritten" do
|
148
|
+
@block_args.should be_nil
|
149
|
+
@rewritten_text.should == "hello @/my-list"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "list slug at beginning of line" do
|
154
|
+
def original_text; "@jacob/my-list"; end
|
155
|
+
|
156
|
+
it "should be rewritten" do
|
157
|
+
@block_args.should == ["@", "jacob", "/my-list"]
|
158
|
+
@rewritten_text.should == "[rewritten]"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "username preceded by alpha-numeric character" do
|
163
|
+
def original_text; "meet@jacob/my-list"; end
|
164
|
+
|
165
|
+
it "should not be rewritten" do
|
166
|
+
@block_args.should be_nil
|
167
|
+
@rewritten_text.should == "meet@jacob/my-list"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "username preceded by non-word character" do
|
172
|
+
def original_text; "great.@jacob/my-list"; end
|
173
|
+
|
174
|
+
it "should be rewritten" do
|
175
|
+
@block_args.should == ["@", "jacob", "/my-list"]
|
176
|
+
@rewritten_text.should == "great.[rewritten]"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context "username containing non-word characters" do
|
181
|
+
def original_text; "@jacob/my-list&^$%^"; end
|
182
|
+
|
183
|
+
it "should be rewritten" do
|
184
|
+
@block_args.should == ["@", "jacob", "/my-list"]
|
185
|
+
@rewritten_text.should == "[rewritten]&^$%^"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context "username over twenty characters" do
|
190
|
+
def original_text
|
191
|
+
@twentyfive_character_list = "a" * 25
|
192
|
+
"@jacob/#{@twentyfive_character_list}12345"
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should be rewritten" do
|
196
|
+
@block_args.should == ["@", "jacob", "/#{@twentyfive_character_list}"]
|
197
|
+
@rewritten_text.should == "[rewritten]12345"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end #}}}
|
201
|
+
|
202
|
+
describe "rewrite hashtags" do #{{{
|
203
|
+
before do
|
204
|
+
@rewritten_text = Twitter::Rewriter.rewrite_hashtags(original_text, &method(:block))
|
205
|
+
end
|
206
|
+
|
207
|
+
context "with an all numeric hashtag" do
|
208
|
+
def original_text; "#123"; end
|
209
|
+
|
210
|
+
it "should not be rewritten" do
|
211
|
+
@block_args.should be_nil
|
212
|
+
@rewritten_text.should == "#123"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context "with a hashtag with alphanumeric characters" do
|
217
|
+
def original_text; "#ab1d"; end
|
218
|
+
|
219
|
+
it "should be rewritten" do
|
220
|
+
@block_args.should == ["#", "ab1d"]
|
221
|
+
@rewritten_text.should == "[rewritten]"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context "with a hashtag with underscores" do
|
226
|
+
def original_text; "#a_b_c_d"; end
|
227
|
+
|
228
|
+
it "should be rewritten" do
|
229
|
+
@block_args.should == ["#", "a_b_c_d"]
|
230
|
+
@rewritten_text.should == "[rewritten]"
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context "with a hashtag that is preceded by a word character" do
|
235
|
+
def original_text; "ab#cd"; end
|
236
|
+
|
237
|
+
it "should not be rewritten" do
|
238
|
+
@block_args.should be_nil
|
239
|
+
@rewritten_text.should == "ab#cd"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
context "with a hashtag that starts with a number but has word characters" do
|
244
|
+
def original_text; "#2ab"; end
|
245
|
+
|
246
|
+
it "should be rewritten" do
|
247
|
+
@block_args.should == ["#", "2ab"]
|
248
|
+
@rewritten_text.should == "[rewritten]"
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
context "with multiple valid hashtags" do
|
253
|
+
def original_text; "I'm frickin' awesome #ab #cd #ef"; end
|
254
|
+
|
255
|
+
it "rewrites each hashtag" do
|
256
|
+
@block_args.should == [["#", "ab"], ["#", "cd"], ["#", "ef"]]
|
257
|
+
@rewritten_text.should == "I'm frickin' awesome [rewritten] [rewritten] [rewritten]"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
context "with a hashtag preceded by a ." do
|
262
|
+
def original_text; "ok, great.#abc"; end
|
263
|
+
|
264
|
+
it "should be rewritten" do
|
265
|
+
@block_args.should == ["#", "abc"]
|
266
|
+
@rewritten_text.should == "ok, great.[rewritten]"
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
context "with a hashtag preceded by a &" do
|
271
|
+
def original_text; "&#nbsp;"; end
|
272
|
+
|
273
|
+
it "should not be rewritten" do
|
274
|
+
@block_args.should be_nil
|
275
|
+
@rewritten_text.should == "&#nbsp;"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
context "with a hashtag that ends in an !" do
|
280
|
+
def original_text; "#great!"; end
|
281
|
+
|
282
|
+
it "should be rewritten, but should not include the !" do
|
283
|
+
@block_args.should == ["#", "great"];
|
284
|
+
@rewritten_text.should == "[rewritten]!"
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
context "with a hashtag followed by Japanese" do
|
289
|
+
def original_text; "#twj_devの"; end
|
290
|
+
|
291
|
+
it "should be rewritten" do
|
292
|
+
@block_args.should == ["#", "twj_devの"];
|
293
|
+
@rewritten_text.should == "[rewritten]"
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context "with a hashtag preceded by a full-width space" do
|
298
|
+
def original_text; "#{[0x3000].pack('U')}#twj_dev"; end
|
299
|
+
|
300
|
+
it "should be rewritten" do
|
301
|
+
@block_args.should == ["#", "twj_dev"];
|
302
|
+
@rewritten_text.should == " [rewritten]"
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
context "with a hashtag followed by a full-width space" do
|
307
|
+
def original_text; "#twj_dev#{[0x3000].pack('U')}"; end
|
308
|
+
|
309
|
+
it "should be rewritten" do
|
310
|
+
@block_args.should == ["#", "twj_dev"];
|
311
|
+
@rewritten_text.should == "[rewritten] "
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context "with a hashtag using full-width hash" do
|
316
|
+
def original_text; "#{[0xFF03].pack('U')}twj_dev"; end
|
317
|
+
|
318
|
+
it "should be rewritten" do
|
319
|
+
@block_args.should == ["#", "twj_dev"];
|
320
|
+
@rewritten_text.should == "[rewritten]"
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
context "with a hashtag containing an accented latin character" do
|
325
|
+
def original_text
|
326
|
+
# the hashtag is #éhashtag
|
327
|
+
"##{[0x00e9].pack('U')}hashtag"
|
328
|
+
end
|
329
|
+
|
330
|
+
it "should be rewritten" do
|
331
|
+
@block_args.should == ["#", "éhashtag"];
|
332
|
+
@rewritten_text.should == "[rewritten]"
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end #}}}
|
336
|
+
|
337
|
+
describe "rewrite urls" do #{{{
|
338
|
+
def url; "http://www.google.com"; end
|
339
|
+
|
340
|
+
before do
|
341
|
+
@rewritten_text = Twitter::Rewriter.rewrite_urls(original_text, &method(:block))
|
342
|
+
end
|
343
|
+
|
344
|
+
context "when embedded in plain text" do
|
345
|
+
def original_text; "On my search engine #{url} I found good links."; end
|
346
|
+
|
347
|
+
it "should be rewritten" do
|
348
|
+
@block_args.should == [url];
|
349
|
+
@rewritten_text.should == "On my search engine [rewritten] I found good links."
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
context "when surrounded by Japanese;" do
|
354
|
+
def original_text; "いまなにしてる#{url}いまなにしてる"; end
|
355
|
+
|
356
|
+
it "should be rewritten" do
|
357
|
+
@block_args.should == [url];
|
358
|
+
@rewritten_text.should == "いまなにしてる[rewritten]いまなにしてる"
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
context "with a path surrounded by parentheses;" do
|
363
|
+
def original_text; "I found a neatness (#{url})"; end
|
364
|
+
|
365
|
+
it "should be rewritten" do
|
366
|
+
@block_args.should == [url];
|
367
|
+
@rewritten_text.should == "I found a neatness ([rewritten])"
|
368
|
+
end
|
369
|
+
|
370
|
+
context "when the URL ends with a slash;" do
|
371
|
+
def url; "http://www.google.com/"; end
|
372
|
+
|
373
|
+
it "should be rewritten" do
|
374
|
+
@block_args.should == [url];
|
375
|
+
@rewritten_text.should == "I found a neatness ([rewritten])"
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
context "when the URL has a path;" do
|
380
|
+
def url; "http://www.google.com/fsdfasdf"; end
|
381
|
+
|
382
|
+
it "should be rewritten" do
|
383
|
+
@block_args.should == [url];
|
384
|
+
@rewritten_text.should == "I found a neatness ([rewritten])"
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
context "when path contains parens" do
|
390
|
+
def original_text; "I found a neatness (#{url})"; end
|
391
|
+
|
392
|
+
it "should be rewritten" do
|
393
|
+
@block_args.should == [url];
|
394
|
+
@rewritten_text.should == "I found a neatness ([rewritten])"
|
395
|
+
end
|
396
|
+
|
397
|
+
context "wikipedia" do
|
398
|
+
def url; "http://en.wikipedia.org/wiki/Madonna_(artist)"; end
|
399
|
+
|
400
|
+
it "should be rewritten" do
|
401
|
+
@block_args.should == [url];
|
402
|
+
@rewritten_text.should == "I found a neatness ([rewritten])"
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
context "IIS session" do
|
407
|
+
def url; "http://msdn.com/S(deadbeef)/page.htm"; end
|
408
|
+
|
409
|
+
it "should be rewritten" do
|
410
|
+
@block_args.should == [url];
|
411
|
+
@rewritten_text.should == "I found a neatness ([rewritten])"
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
context "unbalanced parens" do
|
416
|
+
def url; "http://example.com/i_has_a_("; end
|
417
|
+
|
418
|
+
it "should be rewritten" do
|
419
|
+
@block_args.should == ["http://example.com/i_has_a_"];
|
420
|
+
@rewritten_text.should == "I found a neatness ([rewritten]()"
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
context "balanced parens with a double quote inside" do
|
425
|
+
def url; "http://foo.bar.com/foo_(\")_bar" end
|
426
|
+
|
427
|
+
it "should be rewritten" do
|
428
|
+
@block_args.should == ["http://foo.bar.com/foo_"];
|
429
|
+
@rewritten_text.should == "I found a neatness ([rewritten](\")_bar)"
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
context "balanced parens hiding XSS" do
|
434
|
+
def url; 'http://x.xx.com/("style="color:red"onmouseover="alert(1)' end
|
435
|
+
|
436
|
+
it "should be rewritten" do
|
437
|
+
@block_args.should == ["http://x.xx.com/"];
|
438
|
+
@rewritten_text.should == 'I found a neatness ([rewritten]("style="color:red"onmouseover="alert(1))'
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
context "when preceded by a :" do
|
444
|
+
def original_text; "Check this out @hoverbird:#{url}"; end
|
445
|
+
|
446
|
+
it "should be rewritten" do
|
447
|
+
@block_args.should == [url];
|
448
|
+
@rewritten_text.should == "Check this out @hoverbird:[rewritten]"
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
context "with a URL ending in allowed punctuation" do
|
453
|
+
it "does not consume ending punctuation" do
|
454
|
+
%w| ? ! , . : ; ] ) } = \ ' |.each do |char|
|
455
|
+
Twitter::Rewriter.rewrite_urls("#{url}#{char}") do |url|
|
456
|
+
url.should == url; "[rewritten]"
|
457
|
+
end.should == "[rewritten]#{char}"
|
458
|
+
end
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
context "with a URL preceded in forbidden characters" do
|
463
|
+
it "should be rewritten" do
|
464
|
+
%w| \ ' / ! = |.each do |char|
|
465
|
+
Twitter::Rewriter.rewrite_urls("#{char}#{url}") do |url|
|
466
|
+
"[rewritten]" # should not be called here.
|
467
|
+
end.should == "#{char}[rewritten]"
|
468
|
+
end
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
context "when embedded in a link tag" do
|
473
|
+
def original_text; "<link rel='true'>#{url}</link>"; end
|
474
|
+
|
475
|
+
it "should be rewritten" do
|
476
|
+
@block_args.should == [url];
|
477
|
+
@rewritten_text.should == "<link rel='true'>[rewritten]</link>"
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
context "with multiple URLs" do
|
482
|
+
def original_text; "http://www.links.org link at start of page, link at end http://www.foo.org"; end
|
483
|
+
|
484
|
+
it "should autolink each one" do
|
485
|
+
@block_args.should == [["http://www.links.org"], ["http://www.foo.org"]];
|
486
|
+
@rewritten_text.should == "[rewritten] link at start of page, link at end [rewritten]"
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
context "with multiple URLs in different formats" do
|
491
|
+
def original_text; "http://foo.com https://bar.com http://mail.foobar.org"; end
|
492
|
+
|
493
|
+
it "should autolink each one, in the proper order" do
|
494
|
+
@block_args.should == [["http://foo.com"], ["https://bar.com"], ["http://mail.foobar.org"]];
|
495
|
+
@rewritten_text.should == "[rewritten] [rewritten] [rewritten]"
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
context "with a URL having a long TLD" do
|
500
|
+
def original_text; "Yahoo integriert Facebook http://golem.mobi/0912/71607.html"; end
|
501
|
+
|
502
|
+
it "should autolink it" do
|
503
|
+
@block_args.should == ["http://golem.mobi/0912/71607.html"]
|
504
|
+
@rewritten_text.should == "Yahoo integriert Facebook [rewritten]"
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
context "with a url lacking the protocol" do
|
509
|
+
def original_text; "I like www.foobar.com dudes"; end
|
510
|
+
|
511
|
+
it "does not link at all" do
|
512
|
+
@block_args.should be_nil
|
513
|
+
@rewritten_text.should == "I like www.foobar.com dudes"
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
context "with a @ in a URL" do
|
518
|
+
context "with XSS attack" do
|
519
|
+
def original_text; 'http://x.xx.com/@"style="color:pink"onmouseover=alert(1)//'; end
|
520
|
+
|
521
|
+
it "should not allow XSS follwing @" do
|
522
|
+
@block_args.should == ["http://x.xx.com/"]
|
523
|
+
@rewritten_text.should == '[rewritten]@"style="color:pink"onmouseover=alert(1)//'
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
context "with a username not followed by a /" do
|
528
|
+
def original_text; "http://example.com/@foobar"; end
|
529
|
+
|
530
|
+
it "should link url" do
|
531
|
+
@block_args.should == ["http://example.com/@foobar"]
|
532
|
+
@rewritten_text.should == "[rewritten]"
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
context "with a username followed by a /" do
|
537
|
+
def original_text; "http://example.com/@foobar/"; end
|
538
|
+
|
539
|
+
it "should not link the username but link full url" do
|
540
|
+
@block_args.should == ["http://example.com/@foobar/"]
|
541
|
+
@rewritten_text.should == "[rewritten]"
|
542
|
+
end
|
543
|
+
end
|
544
|
+
end
|
545
|
+
end #}}}
|
546
|
+
end
|
547
|
+
|
548
|
+
# vim: foldmethod=marker
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
$TESTING=true
|
2
|
+
|
3
|
+
# Ruby 1.8 encoding check
|
4
|
+
major, minor, patch = RUBY_VERSION.split('.')
|
5
|
+
if major.to_i == 1 && minor.to_i < 9
|
6
|
+
$KCODE='u'
|
7
|
+
end
|
8
|
+
|
9
|
+
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
10
|
+
|
11
|
+
require 'nokogiri'
|
12
|
+
require 'simplecov'
|
13
|
+
SimpleCov.start do
|
14
|
+
add_group 'Libraries', 'lib'
|
15
|
+
end
|
16
|
+
|
17
|
+
require File.expand_path('../../lib/twitter-text', __FILE__)
|
18
|
+
require File.expand_path('../test_urls', __FILE__)
|
19
|
+
|
20
|
+
RSpec.configure do |config|
|
21
|
+
config.include TestUrls
|
22
|
+
end
|
23
|
+
|
24
|
+
RSpec::Matchers.define :match_autolink_expression do
|
25
|
+
match do |string|
|
26
|
+
!Twitter::Extractor.extract_urls(string).empty?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
RSpec::Matchers.define :match_autolink_expression_in do |text|
|
31
|
+
match do |url|
|
32
|
+
@match_data = Twitter::Regex[:valid_url].match(text)
|
33
|
+
@match_data && @match_data.to_s.strip == url
|
34
|
+
end
|
35
|
+
|
36
|
+
failure_message_for_should do |url|
|
37
|
+
"Expected to find url '#{url}' in text '#{text}', but the match was #{@match_data.captures}'"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
RSpec::Matchers.define :have_autolinked_url do |url, inner_text|
|
42
|
+
match do |text|
|
43
|
+
@link = Nokogiri::HTML(text).search("a[@href='#{url}']")
|
44
|
+
@link &&
|
45
|
+
@link.inner_text &&
|
46
|
+
(inner_text && @link.inner_text == inner_text) || (!inner_text && @link.inner_text == url)
|
47
|
+
end
|
48
|
+
|
49
|
+
failure_message_for_should do |text|
|
50
|
+
"Expected url '#{url}'#{", inner_text '#{inner_text}'" if inner_text} to be autolinked in '#{text}'"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
RSpec::Matchers.define :link_to_screen_name do |screen_name, inner_text|
|
55
|
+
expected = inner_text ? inner_text : screen_name
|
56
|
+
|
57
|
+
match do |text|
|
58
|
+
@link = Nokogiri::HTML(text).search("a.username")
|
59
|
+
@link &&
|
60
|
+
@link.inner_text == expected &&
|
61
|
+
"https://twitter.com/#{screen_name}".downcase.should == @link.first['href']
|
62
|
+
end
|
63
|
+
|
64
|
+
failure_message_for_should do |text|
|
65
|
+
if @link.first
|
66
|
+
"Expected link '#{@link.inner_text}' with href '#{@link.first['href']}' to match screen_name '#{expected}', but it does not."
|
67
|
+
else
|
68
|
+
"Expected screen name '#{screen_name}' to be autolinked in '#{text}', but no link was found."
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
failure_message_for_should_not do |text|
|
73
|
+
"Expected link '#{@link.inner_text}' with href '#{@link.first['href']}' not to match screen_name '#{expected}', but it does."
|
74
|
+
end
|
75
|
+
|
76
|
+
description do
|
77
|
+
"contain a link with the name and href pointing to the expected screen_name"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
RSpec::Matchers.define :link_to_list_path do |list_path, inner_text|
|
82
|
+
expected = inner_text ? inner_text : list_path
|
83
|
+
|
84
|
+
match do |text|
|
85
|
+
@link = Nokogiri::HTML(text).search("a.list-slug")
|
86
|
+
@link &&
|
87
|
+
@link.inner_text == expected &&
|
88
|
+
"https://twitter.com/#{list_path}".downcase.should == @link.first['href']
|
89
|
+
end
|
90
|
+
|
91
|
+
failure_message_for_should do |text|
|
92
|
+
if @link.first
|
93
|
+
"Expected link '#{@link.inner_text}' with href '#{@link.first['href']}' to match the list path '#{expected}', but it does not."
|
94
|
+
else
|
95
|
+
"Expected list path '#{list_path}' to be autolinked in '#{text}', but no link was found."
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
failure_message_for_should_not do |text|
|
100
|
+
"Expected link '#{@link.inner_text}' with href '#{@link.first['href']}' not to match the list path '#{expected}', but it does."
|
101
|
+
end
|
102
|
+
|
103
|
+
description do
|
104
|
+
"contain a link with the list title and an href pointing to the list path"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
RSpec::Matchers.define :have_autolinked_hashtag do |hashtag|
|
109
|
+
match do |text|
|
110
|
+
@link = Nokogiri::HTML(text).search("a[@href='https://twitter.com/#!/search?q=#{hashtag.sub(/^#/, '%23')}']")
|
111
|
+
@link &&
|
112
|
+
@link.inner_text &&
|
113
|
+
@link.inner_text == hashtag
|
114
|
+
end
|
115
|
+
|
116
|
+
failure_message_for_should do |text|
|
117
|
+
if @link.first
|
118
|
+
"Expected link text to be [#{hashtag}], but it was [#{@link.inner_text}] in #{text}"
|
119
|
+
else
|
120
|
+
"Expected hashtag #{hashtag} to be autolinked in '#{text}', but no link was found."
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
failure_message_for_should_not do |text|
|
125
|
+
"Expected link '#{@link.inner_text}' with href '#{@link.first['href']}' not to match the hashtag '#{hashtag}', but it does."
|
126
|
+
end
|
127
|
+
end
|