string_ext_test.rb 14.1 KB
Newer Older
1
# encoding: utf-8
2
require 'date'
3
require 'abstract_unit'
4
require 'inflector_test_cases'
5
require 'constantize_test_cases'
6

7
require 'active_support/inflector'
J
Jeremy Kemper 已提交
8
require 'active_support/core_ext/string'
9
require 'active_support/time'
X
Xavier Noria 已提交
10
require 'active_support/core_ext/string/strip'
11
require 'active_support/core_ext/string/output_safety'
J
Jeremy Kemper 已提交
12

13 14 15 16 17 18 19
module Ace
  module Base
    class Case
    end
  end
end

20
class StringInflectionsTest < Test::Unit::TestCase
21
  include InflectorTestCases
22
  include ConstantizeTestCases
23

X
Xavier Noria 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
  def test_strip_heredoc_on_an_empty_string
    assert_equal '', ''.strip_heredoc
  end

  def test_strip_heredoc_on_a_string_with_no_lines
    assert_equal 'x', 'x'.strip_heredoc
    assert_equal 'x', '    x'.strip_heredoc
  end

  def test_strip_heredoc_on_a_heredoc_with_no_margin
    assert_equal "foo\nbar", "foo\nbar".strip_heredoc
    assert_equal "foo\n  bar", "foo\n  bar".strip_heredoc
  end

  def test_strip_heredoc_on_a_regular_indented_heredoc
    assert_equal "foo\n  bar\nbaz\n", <<-EOS.strip_heredoc
      foo
        bar
      baz
    EOS
  end

46 47 48 49 50 51 52 53 54
  def test_strip_heredoc_on_a_regular_indented_heredoc_with_blank_lines
    assert_equal "foo\n  bar\n\nbaz\n", <<-EOS.strip_heredoc
      foo
        bar

      baz
    EOS
  end

55
  def test_pluralize
56
    SingularToPlural.each do |singular, plural|
57 58 59 60
      assert_equal(plural, singular.pluralize)
    end

    assert_equal("plurals", "plurals".pluralize)
61 62 63 64

    assert_equal("blargles", "blargle".pluralize(0))
    assert_equal("blargle", "blargle".pluralize(1))
    assert_equal("blargles", "blargle".pluralize(2))
65 66 67
  end

  def test_singularize
68
    SingularToPlural.each do |singular, plural|
69 70 71 72
      assert_equal(singular, plural.singularize)
    end
  end

73
  def test_titleize
74
    MixtureToTitleCase.each do |before, titleized|
75 76 77 78
      assert_equal(titleized, before.titleize)
    end
  end

79
  def test_camelize
80
    CamelToUnderscore.each do |camel, underscore|
81 82 83 84
      assert_equal(camel, underscore.camelize)
    end
  end

85 86 87 88
  def test_camelize_lower
    assert_equal('capital', 'Capital'.camelize(:lower))
  end

89
  def test_underscore
90
    CamelToUnderscore.each do |camel, underscore|
91 92
      assert_equal(underscore, camel.underscore)
    end
93

94 95 96 97
    assert_equal "html_tidy", "HTMLTidy".underscore
    assert_equal "html_tidy_generator", "HTMLTidyGenerator".underscore
  end

98
  def test_underscore_to_lower_camel
99
    UnderscoreToLowerCamel.each do |underscored, lower_camel|
100 101 102 103
      assert_equal(lower_camel, underscored.camelize(:lower))
    end
  end

104
  def test_demodulize
105
    assert_equal "Account", "MyApplication::Billing::Account".demodulize
106 107
  end

108 109 110 111
  def test_deconstantize
    assert_equal "MyApplication::Billing", "MyApplication::Billing::Account".deconstantize
  end

112
  def test_foreign_key
113
    ClassNameToForeignKeyWithUnderscore.each do |klass, foreign_key|
114 115 116
      assert_equal(foreign_key, klass.foreign_key)
    end

117
    ClassNameToForeignKeyWithoutUnderscore.each do |klass, foreign_key|
118 119 120 121 122
      assert_equal(foreign_key, klass.foreign_key(false))
    end
  end

  def test_tableize
123
    ClassNameToTableName.each do |class_name, table_name|
124 125 126 127 128
      assert_equal(table_name, class_name.tableize)
    end
  end

  def test_classify
129
    ClassNameToTableName.each do |class_name, table_name|
130 131 132
      assert_equal(class_name, table_name.classify)
    end
  end
133

134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
  def test_string_parameterized_normal
    StringToParameterized.each do |normal, slugged|
      assert_equal(normal.parameterize, slugged)
    end
  end

  def test_string_parameterized_no_separator
    StringToParameterizeWithNoSeparator.each do |normal, slugged|
      assert_equal(normal.parameterize(''), slugged)
    end
  end

  def test_string_parameterized_underscore
    StringToParameterizeWithUnderscore.each do |normal, slugged|
      assert_equal(normal.parameterize('_'), slugged)
    end
  end

152
  def test_humanize
153
    UnderscoreToHuman.each do |underscore, human|
154 155 156 157
      assert_equal(human, underscore.humanize)
    end
  end

J
Jeremy Kemper 已提交
158 159 160 161 162
  def test_ord
    assert_equal 97, 'a'.ord
    assert_equal 97, 'abc'.ord
  end

163 164 165 166 167 168 169 170
  if RUBY_VERSION < '1.9'
    def test_getbyte
      assert_equal 97, 'a'.getbyte(0)
      assert_equal 99, 'abc'.getbyte(2)
      assert_nil   'abc'.getbyte(3)
    end
  end

171 172 173
  def test_string_to_time
    assert_equal Time.utc(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time
    assert_equal Time.local(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time(:local)
174 175
    assert_equal Time.utc(2005, 2, 27, 23, 50, 19, 275038), "2005-02-27T23:50:19.275038".to_time
    assert_equal Time.local(2005, 2, 27, 23, 50, 19, 275038), "2005-02-27T23:50:19.275038".to_time(:local)
176 177
    assert_equal DateTime.civil(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_time
    assert_equal Time.local_time(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_time(:local)
178
    assert_equal Time.utc(2011, 2, 27, 23, 50), "2011-02-27 22:50 -0100".to_time
179
    assert_nil "".to_time
180
  end
181

182
  def test_string_to_datetime
183
    assert_equal DateTime.civil(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_datetime
184 185
    assert_equal 0, "2039-02-27 23:50".to_datetime.offset # use UTC offset
    assert_equal ::Date::ITALY, "2039-02-27 23:50".to_datetime.start # use Ruby's default start value
186
    assert_equal DateTime.civil(2039, 2, 27, 23, 50, 19 + Rational(275038, 1000000), "-04:00"), "2039-02-27T23:50:19.275038-04:00".to_datetime
187
    assert_nil "".to_datetime
188
  end
189

190 191
  def test_string_to_date
    assert_equal Date.new(2005, 2, 27), "2005-02-27".to_date
192
    assert_nil "".to_date
193
  end
194

195 196 197
  def test_access
    s = "hello"
    assert_equal "h", s.at(0)
198

199 200
    assert_equal "llo", s.from(2)
    assert_equal "hel", s.to(2)
201

202 203
    assert_equal "h", s.first
    assert_equal "he", s.first(2)
204
    assert_equal "", s.first(0)
205 206 207

    assert_equal "o", s.last
    assert_equal "llo", s.last(3)
208
    assert_equal "hello", s.last(10)
209
    assert_equal "", s.last(0)
210

211 212 213 214 215
    assert_equal 'x', 'x'.first
    assert_equal 'x', 'x'.first(4)

    assert_equal 'x', 'x'.last
    assert_equal 'x', 'x'.last(4)
216
  end
217

218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
  def test_access_returns_a_real_string
    hash = {}
    hash["h"] = true
    hash["hello123".at(0)] = true
    assert_equal %w(h), hash.keys

    hash = {}
    hash["llo"] = true
    hash["hello".from(2)] = true
    assert_equal %w(llo), hash.keys

    hash = {}
    hash["hel"] = true
    hash["hello".to(2)] = true
    assert_equal %w(hel), hash.keys

    hash = {}
    hash["hello"] = true
    hash["123hello".last(5)] = true
    assert_equal %w(hello), hash.keys

    hash = {}
    hash["hello"] = true
    hash["hello123".first(5)] = true
    assert_equal %w(hello), hash.keys
  end

245
  def test_starts_ends_with_alias
246 247 248 249 250 251 252 253
    s = "hello"
    assert s.starts_with?('h')
    assert s.starts_with?('hel')
    assert !s.starts_with?('el')

    assert s.ends_with?('o')
    assert s.ends_with?('lo')
    assert !s.ends_with?('el')
254
  end
255

256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
  def test_string_squish
    original = %{ A string with tabs(\t\t), newlines(\n\n), and
                  many spaces(  ). }

    expected = "A string with tabs( ), newlines( ), and many spaces( )."

    # Make sure squish returns what we expect:
    assert_equal original.squish,  expected
    # But doesn't modify the original string:
    assert_not_equal original, expected

    # Make sure squish! returns what we expect:
    assert_equal original.squish!, expected
    # And changes the original string:
    assert_equal original, expected
  end
272

273 274 275 276
  def test_string_inquiry
    assert "production".inquiry.production?
    assert !"production".inquiry.development?
  end
277

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
  def test_truncate
    assert_equal "Hello World!", "Hello World!".truncate(12)
    assert_equal "Hello Wor...", "Hello World!!".truncate(12)
  end

  def test_truncate_with_omission_and_seperator
    assert_equal "Hello[...]", "Hello World!".truncate(10, :omission => "[...]")
    assert_equal "Hello[...]", "Hello Big World!".truncate(13, :omission => "[...]", :separator => ' ')
    assert_equal "Hello Big[...]", "Hello Big World!".truncate(14, :omission => "[...]", :separator => ' ')
    assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, :omission => "[...]", :separator => ' ')
  end

  if RUBY_VERSION < '1.9.0'
    def test_truncate_multibyte
      with_kcode 'none' do
        assert_equal "\354\225\210\353\205\225\355...", "\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224".truncate(10)
      end
      with_kcode 'u' do
        assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...",
          "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".truncate(10)
      end
    end
  else
    def test_truncate_multibyte
      assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'),
        "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8').truncate(10)
    end
  end
306

307 308 309 310 311
  def test_constantize
    run_constantize_tests_on do |string|
      string.constantize
    end
  end
312

313 314 315 316 317
  def test_safe_constantize
    run_safe_constantize_tests_on do |string|
      string.safe_constantize
    end
  end
318
end
319 320 321 322 323

class StringBehaviourTest < Test::Unit::TestCase
  def test_acts_like_string
    assert 'Bambi'.acts_like_string?
  end
324 325
end

326
class CoreExtStringMultibyteTest < ActiveSupport::TestCase
327 328 329 330 331
  UNICODE_STRING = 'こにちわ'
  ASCII_STRING = 'ohayo'
  BYTE_STRING = "\270\236\010\210\245"

  def test_core_ext_adds_mb_chars
332
    assert_respond_to UNICODE_STRING, :mb_chars
333 334 335 336 337 338 339 340 341 342 343
  end

  def test_string_should_recognize_utf8_strings
    assert UNICODE_STRING.is_utf8?
    assert ASCII_STRING.is_utf8?
    assert !BYTE_STRING.is_utf8?
  end

  if RUBY_VERSION < '1.9'
    def test_mb_chars_returns_self_when_kcode_not_set
      with_kcode('none') do
344
        assert_kind_of String, UNICODE_STRING.mb_chars
345 346 347 348 349
      end
    end

    def test_mb_chars_returns_an_instance_of_the_chars_proxy_when_kcode_utf8
      with_kcode('UTF8') do
350
        assert_kind_of ActiveSupport::Multibyte.proxy_class, UNICODE_STRING.mb_chars
351 352
      end
    end
353 354 355
  else
    def test_mb_chars_returns_instance_of_proxy_class
      assert_kind_of ActiveSupport::Multibyte.proxy_class, UNICODE_STRING.mb_chars
356 357
    end
  end
358
end
359

360 361 362
class OutputSafetyTest < ActiveSupport::TestCase
  def setup
    @string = "hello"
363 364 365 366 367
    @object = Class.new(Object) do
      def to_s
        "other"
      end
    end.new
368 369 370 371 372 373 374
  end

  test "A string is unsafe by default" do
    assert !@string.html_safe?
  end

  test "A string can be marked safe" do
375 376
    string = @string.html_safe
    assert string.html_safe?
377 378 379
  end

  test "Marking a string safe returns the string" do
380
    assert_equal @string, @string.html_safe
381 382
  end

383 384 385
  test "A fixnum is safe by default" do
    assert 5.html_safe?
  end
386

387 388 389
  test "a float is safe by default" do
    assert 5.7.html_safe?
  end
390 391

  test "An object is unsafe by default" do
392 393
    assert !@object.html_safe?
  end
394

395 396 397
  test "Adding an object to a safe string returns a safe string" do
    string = @string.html_safe
    string << @object
398

399 400
    assert_equal "helloother", string
    assert string.html_safe?
401 402
  end

403
  test "Adding a safe string to another safe string returns a safe string" do
404 405 406
    @other_string = "other".html_safe
    string = @string.html_safe
    @combination = @other_string + string
407 408 409 410 411

    assert_equal "otherhello", @combination
    assert @combination.html_safe?
  end

412 413 414 415
  test "Adding an unsafe string to a safe string escapes it and returns a safe string" do
    @other_string = "other".html_safe
    @combination = @other_string + "<foo>"
    @other_combination = @string + "<foo>"
416

417 418
    assert_equal "other&lt;foo&gt;", @combination
    assert_equal "hello<foo>", @other_combination
419

420
    assert @combination.html_safe?
421 422 423 424 425 426
    assert !@other_combination.html_safe?
  end

  test "Concatting safe onto unsafe yields unsafe" do
    @other_string = "other"

427 428
    string = @string.html_safe
    @other_string.concat(string)
429 430 431
    assert !@other_string.html_safe?
  end

432 433 434 435 436
  test "Concatting unsafe onto safe yields escaped safe" do
    @other_string = "other".html_safe
    string = @other_string.concat("<foo>")
    assert_equal "other&lt;foo&gt;", string
    assert string.html_safe?
437 438 439
  end

  test "Concatting safe onto safe yields safe" do
440
    @other_string = "other".html_safe
441
    string = @string.html_safe
442

443
    @other_string.concat(string)
444 445 446 447 448
    assert @other_string.html_safe?
  end

  test "Concatting safe onto unsafe with << yields unsafe" do
    @other_string = "other"
449
    string = @string.html_safe
450

451
    @other_string << string
452 453 454
    assert !@other_string.html_safe?
  end

455 456 457 458 459
  test "Concatting unsafe onto safe with << yields escaped safe" do
    @other_string = "other".html_safe
    string = @other_string << "<foo>"
    assert_equal "other&lt;foo&gt;", string
    assert string.html_safe?
460 461 462
  end

  test "Concatting safe onto safe with << yields safe" do
463
    @other_string = "other".html_safe
464
    string = @string.html_safe
465

466
    @other_string << string
467 468
    assert @other_string.html_safe?
  end
469 470

  test "Concatting a fixnum to safe always yields safe" do
471 472 473 474
    string = @string.html_safe
    string = string.concat(13)
    assert_equal "hello".concat(13), string
    assert string.html_safe?
475
  end
476 477

  test 'emits normal string yaml' do
478
    assert_equal 'foo'.to_yaml, 'foo'.html_safe.to_yaml(:foo => 1)
479
  end
480 481 482 483 484 485 486 487

  test 'knows whether it is encoding aware' do
    if RUBY_VERSION >= "1.9"
      assert 'ruby'.encoding_aware?
    else
      assert !'ruby'.encoding_aware?
    end
  end
488 489 490 491 492 493

  test "call to_param returns a normal string" do
    string = @string.html_safe
    assert string.html_safe?
    assert !string.to_param.html_safe?
  end
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510

  test "ERB::Util.html_escape should escape unsafe characters" do
    string = '<>&"'
    expected = '&lt;&gt;&amp;&quot;'
    assert_equal expected, ERB::Util.html_escape(string)
  end

  test "ERB::Util.html_escape should correctly handle invalid UTF-8 strings" do
    string = [192, 60].pack('CC')
    expected = 192.chr + "&lt;"
    assert_equal expected, ERB::Util.html_escape(string)
  end

  test "ERB::Util.html_escape should not escape safe strings" do
    string = "<b>hello</b>".html_safe
    assert_equal string, ERB::Util.html_escape(string)
  end
511
end
512 513 514 515 516 517 518

class StringExcludeTest < ActiveSupport::TestCase
  test 'inverse of #include' do
    assert_equal false, 'foo'.exclude?('o')
    assert_equal true, 'foo'.exclude?('p')
  end
end