| | 343 | def test_insignificant_whitespace(self): |
| | 344 | whitespace_tests = { |
| | 345 | # The test tuple contents is (template_content, context_args, stripped_output, unstripped_output) |
| | 346 | # Tags on their own line should collapse the newline before them |
| | 347 | # Trailing newline is not removed |
| | 348 | # Leading whitespace before single template tag |
| | 349 | 'insignificant-whitespace01': ('\n {% templatetag openblock %}\n', {}, '{%\n', |
| | 350 | '\n {%\n'), |
| | 351 | 'insignificant-whitespace02': ('\n{% templatetag openblock %}\n', {}, '{%\n', |
| | 352 | '\n{%\n'), |
| | 353 | 'insignificant-whitespace03': ('{% templatetag openblock %}\n', {}, '{%\n', |
| | 354 | '{%\n'), |
| | 355 | 'insignificant-whitespace04': ('\n\t \t {% templatetag openblock %}\n', {}, '{%\n', |
| | 356 | '\n\t \t {%\n'), |
| | 357 | # Leading whitespace with text before single template tag |
| | 358 | 'insignificant-whitespace05': ('\n some\ttext {% templatetag openblock %}\n', {}, '\n some\ttext {%\n', |
| | 359 | '\n some\ttext {%\n'), |
| | 360 | # Leading line with text before single template tag |
| | 361 | 'insignificant-whitespace06': ('\n some\ttext\n {% templatetag openblock %}\n', {}, '\n some\ttext{%\n', |
| | 362 | '\n some\ttext\n {%\n'), |
| | 363 | 'insignificant-whitespace07': ('\n some\ttext \n \t {% templatetag openblock %}\n', {}, '\n some\ttext {%\n', |
| | 364 | '\n some\ttext \n \t {%\n'), |
| | 365 | # whitespace leading /before/ the newline is not stripped. |
| | 366 | 'insignificant-whitespace08': ('\n some\ttext \t \n {% templatetag openblock %}\n', {}, '\n some\ttext \t {%\n', |
| | 367 | '\n some\ttext \t \n {%\n'), |
| | 368 | # Multiple text lines before tag |
| | 369 | 'insignificant-whitespace09': ('\n some\ntext \t \n {% templatetag openblock %}\n', {}, '\n some\ntext \t {%\n', |
| | 370 | '\n some\ntext \t \n {%\n'), |
| | 371 | 'insignificant-whitespace10': ('\n some \t \n \t text \t \n {% templatetag openblock %}\n', {}, '\n some \t \n \t text \t {%\n', |
| | 372 | '\n some \t \n \t text \t \n {%\n'), |
| | 373 | # Leading whitespace before tag, some text after |
| | 374 | 'insignificant-whitespace11': ('\n \t {% templatetag openblock %} some text\n', {}, '\n \t {% some text\n', |
| | 375 | '\n \t {% some text\n'), |
| | 376 | # Leading whitespace before tag, some text with trailing whitespace after |
| | 377 | 'insignificant-whitespace12': ('\n \t {% templatetag openblock %} some text \t \n', {}, '\n \t {% some text \t \n', |
| | 378 | '\n \t {% some text \t \n'), |
| | 379 | # Whitespace after tag is not removed |
| | 380 | 'insignificant-whitespace13': ('\n \t {% templatetag openblock %} \t \n \t some text \t \n', {}, '{% \t \n \t some text \t \n', |
| | 381 | '\n \t {% \t \n \t some text \t \n'), |
| | 382 | # Multiple lines of leading whitespace. Only one leading newline is removed |
| | 383 | 'insignificant-whitespace14': ('\n\n\n{% templatetag openblock %}\n some text\n', {}, '\n\n{%\n some text\n', |
| | 384 | '\n\n\n{%\n some text\n'), |
| | 385 | # Trailing whitespace after tag |
| | 386 | 'insignificant-whitespace15': ('\n\n\n{% templatetag openblock %}\t \t \t\n some text\n', {}, '\n\n{%\t \t \t\n some text\n', |
| | 387 | '\n\n\n{%\t \t \t\n some text\n'), |
| | 388 | # Removable newline followed by leading whitespace |
| | 389 | 'insignificant-whitespace16': ('\n\n\n\t \t \t{% templatetag openblock %}\n some text\n', {}, '\n\n{%\n some text\n', |
| | 390 | '\n\n\n\t \t \t{%\n some text\n'), |
| | 391 | # Removable leading whitespace and trailing whitespace |
| | 392 | 'insignificant-whitespace17': ('\n\n\n\t \t \t{% templatetag openblock %}\t \t \t\n some text\n', {}, '\n\n{%\t \t \t\n some text\n', |
| | 393 | '\n\n\n\t \t \t{%\t \t \t\n some text\n'), |
| | 394 | # Multiple lines of trailing whitespace. No trailing newline is removed. |
| | 395 | 'insignificant-whitespace18': ('\n{% templatetag openblock %}\n\n\n some text\n', {}, '{%\n\n\n some text\n', |
| | 396 | '\n{%\n\n\n some text\n'), |
| | 397 | 'insignificant-whitespace19': ('\n{% templatetag openblock %}\t \n\n\n some text\n', {}, '{%\t \n\n\n some text\n', |
| | 398 | '\n{%\t \n\n\n some text\n'), |
| | 399 | # Consecutive trimmed lines with tags strips one newline each |
| | 400 | 'insignificant-whitespace20': ( |
| | 401 | '\n{% templatetag openblock %}\n{% templatetag openblock %}\n{% templatetag openblock %}\n some text\n' |
| | 402 | , {}, '{%{%{%\n some text\n', |
| | 403 | '\n{%\n{%\n{%\n some text\n'), |
| | 404 | # Consecutive trimmed lines with tags strips one newline each. Intermediate newlines are preserved |
| | 405 | 'insignificant-whitespace21': ( |
| | 406 | '\n\n{% templatetag openblock %}\n\n{% templatetag openblock %}\n\n{% templatetag openblock %}\n\n some text\n' |
| | 407 | , {}, '\n{%\n{%\n{%\n\n some text\n', |
| | 408 | '\n\n{%\n\n{%\n\n{%\n\n some text\n'), |
| | 409 | # Consecutive trimmed lines with tags strips one newline each. Leading whitespace is stripped but trailing is not |
| | 410 | 'insignificant-whitespace22': ( |
| | 411 | '\n\n\t {% templatetag openblock %}\t \n\n\t {% templatetag openblock %}\t \n\n\t {% templatetag openblock %}\t \n some text\n' |
| | 412 | , {}, '\n{%\t \n{%\t \n{%\t \n some text\n', |
| | 413 | '\n\n\t {%\t \n\n\t {%\t \n\n\t {%\t \n some text\n'), |
| | 414 | # Consecutive trimmed lines with tags strips one newline each. Intermediate whitespace is stripped |
| | 415 | 'insignificant-whitespace23': ( |
| | 416 | '\n\t {% templatetag openblock %}\t \n\t {% templatetag openblock %}\t \n\t {% templatetag openblock %}\t \n some text\n' |
| | 417 | , {}, '{%\t {%\t {%\t \n some text\n', |
| | 418 | '\n\t {%\t \n\t {%\t \n\t {%\t \n some text\n'), |
| | 419 | # Intermediate whitespace on one line is preserved |
| | 420 | # Consecutive tags on one line do not have intermediate whitespace or leading whitespace stripped |
| | 421 | 'insignificant-whitespace24': ( |
| | 422 | '\n\t {% templatetag openblock %}\t \t {% templatetag openblock %}\t \t {% templatetag openblock %}\t \n some text\n' |
| | 423 | , {}, '\n\t {%\t \t {%\t \t {%\t \n some text\n', |
| | 424 | '\n\t {%\t \t {%\t \t {%\t \n some text\n'), |
| | 425 | # Still, only one leading newline is removed. |
| | 426 | 'insignificant-whitespace25': ( |
| | 427 | '\n\n {% templatetag openblock %}\n \t {% templatetag openblock %}\n \t {% templatetag openblock %}\n some text\n' |
| | 428 | , {}, '\n{%{%{%\n some text\n', |
| | 429 | '\n\n {%\n \t {%\n \t {%\n some text\n'), |
| | 430 | # Lines with {# comments #} have the same stripping behavior |
| | 431 | 'insignificant-whitespace26': ( |
| | 432 | '\n\n {% templatetag openblock %}\n \t {# some comment #}\n some text\n' |
| | 433 | , {}, '\n{%\n some text\n', |
| | 434 | '\n\n {%\n \t \n some text\n'), |
| | 435 | # Only {# comments #} |
| | 436 | 'insignificant-whitespace27': ( |
| | 437 | '\n\n {# a comment #}\n \t {# some comment #}\n some text\n' |
| | 438 | , {}, '\n\n some text\n', |
| | 439 | '\n\n \n \t \n some text\n'), |
| | 440 | # Consecutive newlines with tags and comments |
| | 441 | 'insignificant-whitespace28': ( |
| | 442 | '\n\t {% templatetag openblock %}\t \n\t {# some comment #}\t \n\t {% templatetag openblock %}\t \n some text\n' |
| | 443 | , {}, '{%\t \t {%\t \n some text\n', |
| | 444 | '\n\t {%\t \n\t \t \n\t {%\t \n some text\n'), |
| | 445 | |
| | 446 | # Lines with only {{ values }} have the same stripping behavior |
| | 447 | 'insignificant-whitespace29': ( |
| | 448 | '\n {% templatetag openblock %}\t\n \t {{ spam }}\t \n \t {% templatetag openblock %}\t \n some text\n' |
| | 449 | , {"spam" : "ham"}, '{%\tham\t {%\t \n some text\n', |
| | 450 | '\n {%\t\n \t ham\t \n \t {%\t \n some text\n'), |
| | 451 | 'insignificant-whitespace30': ( |
| | 452 | '\n\n {% templatetag openblock %}\t\n\n \t {{ spam }}\t \n\n \t {% templatetag openblock %}\t \n some text\n' |
| | 453 | , {"spam" : "ham"}, '\n{%\t\nham\t \n{%\t \n some text\n', |
| | 454 | '\n\n {%\t\n\n \t ham\t \n\n \t {%\t \n some text\n'), |
| | 455 | ## Leading whitespace not stripped when followed by anything. See insignificant-whitespace24 |
| | 456 | 'insignificant-whitespace31': ( |
| | 457 | '\n {% templatetag openblock %}\t \t {{ spam }}\t \t {% templatetag openblock %}\t \n some text\n' |
| | 458 | , {"spam" : "ham"}, '\n {%\t \t ham\t \t {%\t \n some text\n', |
| | 459 | '\n {%\t \t ham\t \t {%\t \n some text\n'), |
| | 460 | # {{ value }} {% tag %} {{ value }} this time |
| | 461 | 'insignificant-whitespace32': ( |
| | 462 | '\n {{ spam }}\t\n \t {% templatetag openblock %}\t \n \t {{ spam }}\t \n some text\n' |
| | 463 | , {"spam" : "ham"}, 'ham\t{%\t ham\t \n some text\n', |
| | 464 | '\n ham\t\n \t {%\t \n \t ham\t \n some text\n'), |
| | 465 | |
| | 466 | # Invalid stuff is still invalid |
| | 467 | # Newlines inside begin-end tokens, even in {# comments #}, make it not a tag. |
| | 468 | 'insignificant-whitespace33': ( |
| | 469 | '\n\n {# \n{% templatetag openblock #}\t \n some text\n' |
| | 470 | , {}, '\n\n {# \n{% templatetag openblock #}\t \n some text\n', |
| | 471 | '\n\n {# \n{% templatetag openblock #}\t \n some text\n'), |
| | 472 | # Complete comment matching tags on one line are processed |
| | 473 | 'insignificant-whitespace34': ( |
| | 474 | '\n\n {# \n{# templatetag openblock #}\t \n some text\n' |
| | 475 | , {}, '\n\n {# \t \n some text\n', |
| | 476 | '\n\n {# \n\t \n some text\n'), |
| | 477 | 'insignificant-whitespace35': ( |
| | 478 | '\n\n {# \n{# templatetag openblock\n #}\t \n some text\n' |
| | 479 | , {}, '\n\n {# \n{# templatetag openblock\n #}\t \n some text\n', |
| | 480 | '\n\n {# \n{# templatetag openblock\n #}\t \n some text\n'), |
| | 481 | 'insignificant-whitespace36': ( |
| | 482 | '\n\n {# \n{{ some comment #}\t \n some text\n' |
| | 483 | , {}, '\n\n {# \n{{ some comment #}\t \n some text\n', |
| | 484 | '\n\n {# \n{{ some comment #}\t \n some text\n'), |
| | 485 | 'insignificant-whitespace37': ( |
| | 486 | '\n\n {# \n \t {% templatetag openblock #}\t \n some text\n' |
| | 487 | , {}, '\n\n {# \n \t {% templatetag openblock #}\t \n some text\n', |
| | 488 | '\n\n {# \n \t {% templatetag openblock #}\t \n some text\n'), |
| | 489 | 'insignificant-whitespace38': ( |
| | 490 | "\n\n {# templatetag openblock #\n}\t \n some text\n" |
| | 491 | , {}, "\n\n {# templatetag openblock #\n}\t \n some text\n", |
| | 492 | "\n\n {# templatetag openblock #\n}\t \n some text\n" ), |
| | 493 | 'insignificant-whitespace39': ( |
| | 494 | "\n\n {% templatetag openblock %\n}\t \n some text\n" |
| | 495 | , {}, "\n\n {% templatetag openblock %\n}\t \n some text\n", |
| | 496 | "\n\n {% templatetag openblock %\n}\t \n some text\n" ), |
| | 497 | 'insignificant-whitespace40': ( |
| | 498 | "\n\n {{ templatetag openblock }\n}\t \n some text\n" |
| | 499 | , {}, "\n\n {{ templatetag openblock }\n}\t \n some text\n", |
| | 500 | "\n\n {{ templatetag openblock }\n}\t \n some text\n" ), |
| | 501 | 'insignificant-whitespace41': ( |
| | 502 | "\n\n {\n# {# templatetag openblock #}\t \n some text\n" |
| | 503 | , {}, "\n\n {\n# \t \n some text\n", |
| | 504 | "\n\n {\n# \t \n some text\n"), |
| | 505 | 'insignificant-whitespace42': ( |
| | 506 | "\n\n {\n {# templatetag openblock #}\t \n some text\n" |
| | 507 | , {}, "\n\n {\t \n some text\n", |
| | 508 | "\n\n {\n \t \n some text\n"), |
| | 509 | 'insignificant-whitespace43': ( |
| | 510 | "\n{{# foo #};{# bar #}\n" |
| | 511 | , {}, "\n{;\n", |
| | 512 | "\n{;\n"), |
| | 513 | } |
| | 514 | tests = whitespace_tests.items() |
| | 515 | tests.sort() |
| | 516 | |
| | 517 | # Register our custom template loader. |
| | 518 | def test_whitespace_loader(template_name, template_dirs=None): |
| | 519 | "A custom template loader that loads the unit-test templates." |
| | 520 | try: |
| | 521 | return (whitespace_tests[template_name][0] , "test:%s" % template_name) |
| | 522 | except KeyError: |
| | 523 | raise template.TemplateDoesNotExist, template_name |
| | 524 | |
| | 525 | old_template_loaders = loader.template_source_loaders |
| | 526 | loader.template_source_loaders = [test_whitespace_loader] |
| | 527 | |
| | 528 | failures = [] |
| | 529 | |
| | 530 | old_strip_leading_whitespace = settings.TEMPLATE_STRIP_LEADING_WHITESPACE |
| | 531 | |
| | 532 | for name, vals in tests: |
| | 533 | for strip_leading_whitespace in (True, False): |
| | 534 | settings.TEMPLATE_STRIP_LEADING_WHITESPACE = strip_leading_whitespace |
| | 535 | test_template = loader.get_template(name) |
| | 536 | result = vals[2] if strip_leading_whitespace else vals[3] |
| | 537 | output = self.render(test_template, vals) |
| | 538 | |
| | 539 | if output != result: |
| | 540 | failures.append("Whitespace test: %s -- FAILED. Expected %r, got %r" % (name, result, output)) |
| | 541 | |
| | 542 | loader.template_source_loaders = old_template_loaders |
| | 543 | settings.TEMPLATE_STRIP_LEADING_WHITESPACE = old_strip_leading_whitespace |
| | 544 | |
| | 545 | self.assertEqual(failures, [], "Tests failed:\n%s\n%s" % |
| | 546 | ('-'*70, ("\n%s\n" % ('-'*70)).join(failures))) |
| | 547 | |