string_ext_test.rb 14.2 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 < ActiveSupport::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
  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)
166 167
    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)
168 169
    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)
170
    assert_equal Time.utc(2011, 2, 27, 23, 50), "2011-02-27 22:50 -0100".to_time
171
    assert_nil "".to_time
172
  end
173

174
  def test_string_to_datetime
175
    assert_equal DateTime.civil(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_datetime
176 177
    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
178
    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
179
    assert_nil "".to_datetime
180
  end
181

182 183
  def test_string_to_date
    assert_equal Date.new(2005, 2, 27), "2005-02-27".to_date
184
    assert_nil "".to_date
185
  end
186

187 188 189
  def test_access
    s = "hello"
    assert_equal "h", s.at(0)
190

191 192
    assert_equal "llo", s.from(2)
    assert_equal "hel", s.to(2)
193

194 195
    assert_equal "h", s.first
    assert_equal "he", s.first(2)
196
    assert_equal "", s.first(0)
197 198 199

    assert_equal "o", s.last
    assert_equal "llo", s.last(3)
200
    assert_equal "hello", s.last(10)
201
    assert_equal "", s.last(0)
202

203 204 205 206 207
    assert_equal 'x', 'x'.first
    assert_equal 'x', 'x'.first(4)

    assert_equal 'x', 'x'.last
    assert_equal 'x', 'x'.last(4)
208
  end
209

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
  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

237
  def test_starts_ends_with_alias
238 239 240 241 242 243 244 245
    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')
246
  end
247

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
  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
264

265 266 267 268
  def test_string_inquiry
    assert "production".inquiry.production?
    assert !"production".inquiry.development?
  end
269

270 271 272 273 274 275 276 277 278 279 280 281
  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

282 283 284 285 286 287
  def test_truncate_with_omission_and_regexp_seperator
    assert_equal "Hello[...]", "Hello Big World!".truncate(13, :omission => "[...]", :separator => /\s/)
    assert_equal "Hello Big[...]", "Hello Big World!".truncate(14, :omission => "[...]", :separator => /\s/)
    assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, :omission => "[...]", :separator => /\s/)
  end

288 289 290
  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)
291
  end
292

293 294 295 296 297
  def test_constantize
    run_constantize_tests_on do |string|
      string.constantize
    end
  end
298

299 300 301 302 303
  def test_safe_constantize
    run_safe_constantize_tests_on do |string|
      string.safe_constantize
    end
  end
304
end
305

306
class StringBehaviourTest < ActiveSupport::TestCase
307 308 309
  def test_acts_like_string
    assert 'Bambi'.acts_like_string?
  end
310 311
end

312
class CoreExtStringMultibyteTest < ActiveSupport::TestCase
313 314 315 316 317
  UNICODE_STRING = 'こにちわ'
  ASCII_STRING = 'ohayo'
  BYTE_STRING = "\270\236\010\210\245"

  def test_core_ext_adds_mb_chars
318
    assert_respond_to UNICODE_STRING, :mb_chars
319 320 321 322 323 324 325 326
  end

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

327 328
  def test_mb_chars_returns_instance_of_proxy_class
    assert_kind_of ActiveSupport::Multibyte.proxy_class, UNICODE_STRING.mb_chars
329
  end
330
end
331

332 333 334
class OutputSafetyTest < ActiveSupport::TestCase
  def setup
    @string = "hello"
335 336 337 338 339
    @object = Class.new(Object) do
      def to_s
        "other"
      end
    end.new
340 341 342 343 344 345 346
  end

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

  test "A string can be marked safe" do
347 348
    string = @string.html_safe
    assert string.html_safe?
349 350 351
  end

  test "Marking a string safe returns the string" do
352
    assert_equal @string, @string.html_safe
353 354
  end

355 356 357
  test "A fixnum is safe by default" do
    assert 5.html_safe?
  end
358

359 360 361
  test "a float is safe by default" do
    assert 5.7.html_safe?
  end
362 363

  test "An object is unsafe by default" do
364 365
    assert !@object.html_safe?
  end
366

367 368 369
  test "Adding an object to a safe string returns a safe string" do
    string = @string.html_safe
    string << @object
370

371 372
    assert_equal "helloother", string
    assert string.html_safe?
373 374
  end

375
  test "Adding a safe string to another safe string returns a safe string" do
376 377 378
    @other_string = "other".html_safe
    string = @string.html_safe
    @combination = @other_string + string
379 380 381 382 383

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

384 385 386 387
  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>"
388

389 390
    assert_equal "other&lt;foo&gt;", @combination
    assert_equal "hello<foo>", @other_combination
391

392
    assert @combination.html_safe?
393 394 395 396 397 398
    assert !@other_combination.html_safe?
  end

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

399 400
    string = @string.html_safe
    @other_string.concat(string)
401 402 403
    assert !@other_string.html_safe?
  end

404 405 406 407 408
  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?
409 410 411
  end

  test "Concatting safe onto safe yields safe" do
412
    @other_string = "other".html_safe
413
    string = @string.html_safe
414

415
    @other_string.concat(string)
416 417 418 419 420
    assert @other_string.html_safe?
  end

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

423
    @other_string << string
424 425 426
    assert !@other_string.html_safe?
  end

427 428 429 430 431
  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?
432 433 434
  end

  test "Concatting safe onto safe with << yields safe" do
435
    @other_string = "other".html_safe
436
    string = @string.html_safe
437

438
    @other_string << string
439 440
    assert @other_string.html_safe?
  end
441

442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
  test "Concatting safe onto unsafe with % yields unsafe" do
    @other_string = "other%s"
    string = @string.html_safe

    @other_string = @other_string % string
    assert !@other_string.html_safe?
  end

  test "Concatting unsafe onto safe with % yields escaped safe" do
    @other_string = "other%s".html_safe
    string = @other_string % "<foo>"

    assert_equal "other&lt;foo&gt;", string
    assert string.html_safe?
  end

  test "Concatting safe onto safe with % yields safe" do
    @other_string = "other%s".html_safe
    string = @string.html_safe

    @other_string = @other_string % string
    assert @other_string.html_safe?
  end

466 467
  test "Concatting with % doesn't modify a string" do
    @other_string = ["<p>", "<b>", "<h1>"]
468
    _ = "%s %s %s".html_safe % @other_string
469 470 471 472

    assert_equal ["<p>", "<b>", "<h1>"], @other_string
  end

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

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

  test 'knows whether it is encoding aware' do
485 486 487
    assert_deprecated do
      assert 'ruby'.encoding_aware?
    end
488
  end
489 490 491 492 493 494

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

  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
512
end
513 514 515 516 517 518 519

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