twitter-text-editted 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- 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.rb +22 -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/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 +193 -0
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
|
data/spec/test_urls.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TestUrls
|
4
|
+
VALID = [
|
5
|
+
"http://google.com",
|
6
|
+
"http://foobar.com/#",
|
7
|
+
"http://google.com/#foo",
|
8
|
+
"http://google.com/#search?q=iphone%20-filter%3Alinks",
|
9
|
+
"http://twitter.com/#search?q=iphone%20-filter%3Alinks",
|
10
|
+
"http://somedomain.com/index.php?path=/abc/def/",
|
11
|
+
"http://www.boingboing.net/2007/02/14/katamari_damacy_phon.html",
|
12
|
+
"http://somehost.com:3000",
|
13
|
+
"http://xo.com/~matthew+%-x",
|
14
|
+
"http://en.wikipedia.org/wiki/Primer_(film)",
|
15
|
+
"http://www.ams.org/bookstore-getitem/item=mbk-59",
|
16
|
+
"http://chilp.it/?77e8fd",
|
17
|
+
"http://tell.me/why",
|
18
|
+
"http://longtlds.info",
|
19
|
+
"http://✪df.ws/ejp",
|
20
|
+
"http://日本.com",
|
21
|
+
"http://search.twitter.com/search?q=avro&lang=en",
|
22
|
+
"http://mrs.domain-dash.biz",
|
23
|
+
"http://x.com/has/one/char/domain",
|
24
|
+
"http://t.co/nwcLTFF",
|
25
|
+
"http://sub_domain-dash.twitter.com",
|
26
|
+
"http://a.b.cd",
|
27
|
+
"http://a_b.c-d.com",
|
28
|
+
"http://a-b.b.com",
|
29
|
+
"http://twitter-dash.com",
|
30
|
+
"http://msdn.microsoft.com/ja-jp/library/system.net.httpwebrequest(v=VS.100).aspx",
|
31
|
+
"www.foobar.com",
|
32
|
+
"WWW.FOOBAR.COM",
|
33
|
+
"www.foobar.co.jp",
|
34
|
+
"http://t.co",
|
35
|
+
"t.co/nwcLTFF"
|
36
|
+
] unless defined?(TestUrls::VALID)
|
37
|
+
|
38
|
+
INVALID = [
|
39
|
+
"http://no-tld",
|
40
|
+
"http://tld-too-short.x",
|
41
|
+
"http://-doman_dash.com",
|
42
|
+
"http://_leadingunderscore.twitter.com",
|
43
|
+
"http://trailingunderscore_.twitter.com",
|
44
|
+
"http://-leadingdash.twitter.com",
|
45
|
+
"http://trailingdash-.twitter.com",
|
46
|
+
"http://-leadingdash.com",
|
47
|
+
"http://trailingdash-.com",
|
48
|
+
"http://no_underscores.com",
|
49
|
+
"http://test.c_o_m",
|
50
|
+
"http://test.c-o-m",
|
51
|
+
"http://twitt#{[0x202A].pack('U')}er.com",
|
52
|
+
"http://twitt#{[0x202B].pack('U')}er.com",
|
53
|
+
"http://twitt#{[0x202C].pack('U')}er.com",
|
54
|
+
"http://twitt#{[0x202D].pack('U')}er.com",
|
55
|
+
"http://twitt#{[0x202E].pack('U')}er.com"
|
56
|
+
] unless defined?(TestUrls::INVALID)
|
57
|
+
|
58
|
+
TCO = [
|
59
|
+
"http://t.co/P53cv5yO!",
|
60
|
+
"http://t.co/fQJmiPGg***",
|
61
|
+
"http://t.co/pbY2NfTZ's",
|
62
|
+
"http://t.co/2vYHpAc5;",
|
63
|
+
"http://t.co/ulYGBYSo:",
|
64
|
+
"http://t.co/GeT4bSiw=win",
|
65
|
+
"http://t.co/8MkmHU0k+fun",
|
66
|
+
"http://t.co/TKLp64dY.yes,",
|
67
|
+
"http://t.co/8vuO27cI$$",
|
68
|
+
"http://t.co/rPYTvdA8/",
|
69
|
+
"http://t.co/WvtMw5ku%",
|
70
|
+
"http://t.co/8t7G3ddS#",
|
71
|
+
"http://t.co/nfHNJDV2/#!",
|
72
|
+
"http://t.co/gK6NOXHs[good]",
|
73
|
+
"http://t.co/dMrT0o1Y]bad",
|
74
|
+
"http://t.co/FNkPfmii-",
|
75
|
+
"http://t.co/sMgS3pjI_oh",
|
76
|
+
"http://t.co/F8Dq3Plb~",
|
77
|
+
"http://t.co/ivvH58vC&help",
|
78
|
+
"http://t.co/iUBL15zD|NZ5KYLQ8"
|
79
|
+
] unless defined?(TestUrls::TCO)
|
80
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
3
|
+
|
4
|
+
major, minor, patch = RUBY_VERSION.split('.')
|
5
|
+
if major.to_i == 1 && minor.to_i < 9
|
6
|
+
describe "base" do
|
7
|
+
before do
|
8
|
+
$KCODE = 'NONE'
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
$KCODE = 'u'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should raise with invalid KCODE on Ruby < 1.9" do
|
16
|
+
lambda do
|
17
|
+
require 'twitter-text'
|
18
|
+
end.should raise_error
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
3
|
+
|
4
|
+
describe Twitter::Unicode do
|
5
|
+
|
6
|
+
it "should lazy-init constants" do
|
7
|
+
Twitter::Unicode.const_defined?(:UFEB6).should == false
|
8
|
+
Twitter::Unicode::UFEB6.should_not be_nil
|
9
|
+
Twitter::Unicode::UFEB6.should be_kind_of(String)
|
10
|
+
Twitter::Unicode.const_defined?(:UFEB6).should == true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return corresponding character" do
|
14
|
+
Twitter::Unicode::UFEB6.should == [0xfeb6].pack('U')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should allow lowercase notation" do
|
18
|
+
Twitter::Unicode::Ufeb6.should == Twitter::Unicode::UFEB6
|
19
|
+
Twitter::Unicode::Ufeb6.should === Twitter::Unicode::UFEB6
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should allow underscore notation" do
|
23
|
+
Twitter::Unicode::U_FEB6.should == Twitter::Unicode::UFEB6
|
24
|
+
Twitter::Unicode::U_FEB6.should === Twitter::Unicode::UFEB6
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should raise on invalid codepoints" do
|
28
|
+
lambda { Twitter::Unicode::FFFFFF }.should raise_error(NameError)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
3
|
+
|
4
|
+
class TestValidation
|
5
|
+
include Twitter::Validation
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Twitter::Validation do
|
9
|
+
|
10
|
+
it "should disallow invalid BOM character" do
|
11
|
+
TestValidation.new.tweet_invalid?("Bom:#{Twitter::Unicode::UFFFE}").should == :invalid_characters
|
12
|
+
TestValidation.new.tweet_invalid?("Bom:#{Twitter::Unicode::UFEFF}").should == :invalid_characters
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should disallow invalid U+FFFF character" do
|
16
|
+
TestValidation.new.tweet_invalid?("Bom:#{Twitter::Unicode::UFFFF}").should == :invalid_characters
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should disallow direction change characters" do
|
20
|
+
[0x202A, 0x202B, 0x202C, 0x202D, 0x202E].map{|cp| [cp].pack('U') }.each do |char|
|
21
|
+
TestValidation.new.tweet_invalid?("Invalid:#{char}").should == :invalid_characters
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should disallow non-Unicode" do
|
26
|
+
TestValidation.new.tweet_invalid?("not-Unicode:\xfff0").should == :invalid_characters
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should allow <= 140 combined accent characters" do
|
30
|
+
char = [0x65, 0x0301].pack('U')
|
31
|
+
TestValidation.new.tweet_invalid?(char * 139).should == false
|
32
|
+
TestValidation.new.tweet_invalid?(char * 140).should == false
|
33
|
+
TestValidation.new.tweet_invalid?(char * 141).should == :too_long
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should allow <= 140 multi-byte characters" do
|
37
|
+
char = [ 0x1d106 ].pack('U')
|
38
|
+
TestValidation.new.tweet_invalid?(char * 139).should == false
|
39
|
+
TestValidation.new.tweet_invalid?(char * 140).should == false
|
40
|
+
TestValidation.new.tweet_invalid?(char * 141).should == :too_long
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'test/unit'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
# Ruby 1.8 encoding check
|
7
|
+
major, minor, patch = RUBY_VERSION.split('.')
|
8
|
+
if major.to_i == 1 && minor.to_i < 9
|
9
|
+
$KCODE='u'
|
10
|
+
end
|
11
|
+
|
12
|
+
require File.expand_path('../../lib/twitter-text', __FILE__)
|
13
|
+
|
14
|
+
class ConformanceTest < Test::Unit::TestCase
|
15
|
+
include Twitter::Extractor
|
16
|
+
include Twitter::Autolink
|
17
|
+
include Twitter::HitHighlighter
|
18
|
+
include Twitter::Validation
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
%w(description expected text json hits).each do |key|
|
23
|
+
define_method key.to_sym do
|
24
|
+
@test_info[key]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def assert_equal_without_attribute_order(expected, actual, failure_message = nil)
|
29
|
+
assert_block(build_message(failure_message, "<?> expected but was\n<?>", expected, actual)) do
|
30
|
+
equal_nodes?(Nokogiri::HTML(expected).root, Nokogiri::HTML(actual).root)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def equal_nodes?(expected, actual)
|
35
|
+
return false unless expected.name == actual.name
|
36
|
+
return false unless ordered_attributes(expected) == ordered_attributes(actual)
|
37
|
+
return false if expected.text? && actual.text? && expected.content != actual.content
|
38
|
+
|
39
|
+
expected.children.each_with_index do |child, index|
|
40
|
+
return false unless equal_nodes?(child, actual.children[index])
|
41
|
+
end
|
42
|
+
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def ordered_attributes(element)
|
47
|
+
element.attribute_nodes.map{|attr| [attr.name, attr.value]}.sort
|
48
|
+
end
|
49
|
+
|
50
|
+
CONFORMANCE_DIR = ENV['CONFORMANCE_DIR'] || File.expand_path("../twitter-text-conformance", __FILE__)
|
51
|
+
|
52
|
+
def self.def_conformance_test(file, test_type, &block)
|
53
|
+
yaml = YAML.load_file(File.join(CONFORMANCE_DIR, file))
|
54
|
+
raise "No such test suite: #{test_type.to_s}" unless yaml["tests"][test_type.to_s]
|
55
|
+
|
56
|
+
yaml["tests"][test_type.to_s].each do |test_info|
|
57
|
+
name = :"test_#{test_type}_#{test_info['description']}"
|
58
|
+
define_method name do
|
59
|
+
@test_info = test_info
|
60
|
+
instance_eval(&block)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
public
|
66
|
+
|
67
|
+
# Extractor Conformance
|
68
|
+
def_conformance_test("extract.yml", :replies) do
|
69
|
+
assert_equal expected, extract_reply_screen_name(text), description
|
70
|
+
end
|
71
|
+
|
72
|
+
def_conformance_test("extract.yml", :mentions) do
|
73
|
+
assert_equal expected, extract_mentioned_screen_names(text), description
|
74
|
+
end
|
75
|
+
|
76
|
+
def_conformance_test("extract.yml", :mentions_with_indices) do
|
77
|
+
e = expected.map{|elem| elem.inject({}){|h, (k,v)| h[k.to_sym] = v; h} }
|
78
|
+
assert_equal e, extract_mentioned_screen_names_with_indices(text), description
|
79
|
+
end
|
80
|
+
|
81
|
+
def_conformance_test("extract.yml", :mentions_or_lists_with_indices) do
|
82
|
+
e = expected.map{|elem| elem.inject({}){|h, (k,v)| h[k.to_sym] = v; h} }
|
83
|
+
assert_equal e, extract_mentions_or_lists_with_indices(text), description
|
84
|
+
end
|
85
|
+
|
86
|
+
def_conformance_test("extract.yml", :urls) do
|
87
|
+
assert_equal expected, extract_urls(text), description
|
88
|
+
expected.each do |expected_url|
|
89
|
+
assert_equal true, valid_url?(expected_url, true, false), "expected url [#{expected_url}] not valid"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def_conformance_test("extract.yml", :urls_with_indices) do
|
94
|
+
e = expected.map{|elem| elem.inject({}){|h, (k,v)| h[k.to_sym] = v; h} }
|
95
|
+
assert_equal e, extract_urls_with_indices(text), description
|
96
|
+
end
|
97
|
+
|
98
|
+
def_conformance_test("extract.yml", :hashtags) do
|
99
|
+
assert_equal expected, extract_hashtags(text), description
|
100
|
+
end
|
101
|
+
|
102
|
+
def_conformance_test("extract.yml", :hashtags_with_indices) do
|
103
|
+
e = expected.map{|elem| elem.inject({}){|h, (k,v)| h[k.to_sym] = v; h} }
|
104
|
+
assert_equal e, extract_hashtags_with_indices(text), description
|
105
|
+
end
|
106
|
+
|
107
|
+
def_conformance_test("extract.yml", :cashtags) do
|
108
|
+
assert_equal expected, extract_cashtags(text), description
|
109
|
+
end
|
110
|
+
|
111
|
+
def_conformance_test("extract.yml", :cashtags_with_indices) do
|
112
|
+
e = expected.map{|elem| elem.inject({}){|h, (k,v)| h[k.to_sym] = v; h} }
|
113
|
+
assert_equal e, extract_cashtags_with_indices(text), description
|
114
|
+
end
|
115
|
+
|
116
|
+
# Autolink Conformance
|
117
|
+
def_conformance_test("autolink.yml", :usernames) do
|
118
|
+
assert_equal_without_attribute_order expected, auto_link_usernames_or_lists(text, :suppress_no_follow => true), description
|
119
|
+
end
|
120
|
+
|
121
|
+
def_conformance_test("autolink.yml", :lists) do
|
122
|
+
assert_equal_without_attribute_order expected, auto_link_usernames_or_lists(text, :suppress_no_follow => true), description
|
123
|
+
end
|
124
|
+
|
125
|
+
def_conformance_test("autolink.yml", :urls) do
|
126
|
+
assert_equal_without_attribute_order expected, auto_link_urls(text, :suppress_no_follow => true), description
|
127
|
+
end
|
128
|
+
|
129
|
+
def_conformance_test("autolink.yml", :hashtags) do
|
130
|
+
assert_equal_without_attribute_order expected, auto_link_hashtags(text, :suppress_no_follow => true), description
|
131
|
+
end
|
132
|
+
|
133
|
+
def_conformance_test("autolink.yml", :cashtags) do
|
134
|
+
assert_equal_without_attribute_order expected, auto_link_cashtags(text, :suppress_no_follow => true), description
|
135
|
+
end
|
136
|
+
|
137
|
+
def_conformance_test("autolink.yml", :all) do
|
138
|
+
assert_equal_without_attribute_order expected, auto_link(text, :suppress_no_follow => true), description
|
139
|
+
end
|
140
|
+
|
141
|
+
def_conformance_test("autolink.yml", :json) do
|
142
|
+
assert_equal_without_attribute_order expected, auto_link_with_json(text, MultiJson.load(json), :suppress_no_follow => true), description
|
143
|
+
end
|
144
|
+
|
145
|
+
# HitHighlighter Conformance
|
146
|
+
def_conformance_test("hit_highlighting.yml", :plain_text) do
|
147
|
+
assert_equal expected, hit_highlight(text, hits), description
|
148
|
+
end
|
149
|
+
|
150
|
+
def_conformance_test("hit_highlighting.yml", :with_links) do
|
151
|
+
assert_equal expected, hit_highlight(text, hits), description
|
152
|
+
end
|
153
|
+
|
154
|
+
# Validation Conformance
|
155
|
+
def_conformance_test("validate.yml", :tweets) do
|
156
|
+
assert_equal expected, valid_tweet_text?(text), description
|
157
|
+
end
|
158
|
+
|
159
|
+
def_conformance_test("validate.yml", :usernames) do
|
160
|
+
assert_equal expected, valid_username?(text), description
|
161
|
+
end
|
162
|
+
|
163
|
+
def_conformance_test("validate.yml", :lists) do
|
164
|
+
assert_equal expected, valid_list?(text), description
|
165
|
+
end
|
166
|
+
|
167
|
+
def_conformance_test("validate.yml", :urls) do
|
168
|
+
assert_equal expected, valid_url?(text), description
|
169
|
+
end
|
170
|
+
|
171
|
+
def_conformance_test("validate.yml", :urls_without_protocol) do
|
172
|
+
assert_equal expected, valid_url?(text, true, false), description
|
173
|
+
end
|
174
|
+
|
175
|
+
def_conformance_test("validate.yml", :hashtags) do
|
176
|
+
assert_equal expected, valid_hashtag?(text), description
|
177
|
+
end
|
178
|
+
|
179
|
+
def_conformance_test("validate.yml", :lengths) do
|
180
|
+
assert_equal expected, tweet_length(text), description
|
181
|
+
end
|
182
|
+
end
|