| | 390 | def test_insignificant_whitespace(self): |
| | 391 | whitespace_tests = { |
| | 392 | # The test tuple contents is (template_content, context_args, stripped_output, unstripped_output) |
| | 393 | # Tags on their own line should collapse the newline before them |
| | 394 | # Trailing newline is not removed |
| | 395 | # Leading whitespace before single template tag |
| | 396 | 'insignificant-whitespace01': ('\n {% templatetag openblock %}\n', {}, '{%\n', |
| | 397 | '\n {%\n'), |
| | 398 | 'insignificant-whitespace02': ('\n{% templatetag openblock %}\n', {}, '{%\n', |
| | 399 | '\n{%\n'), |
| | 400 | 'insignificant-whitespace03': ('{% templatetag openblock %}\n', {}, '{%\n', |
| | 401 | '{%\n'), |
| | 402 | 'insignificant-whitespace04': ('\n\t \t {% templatetag openblock %}\n', {}, '{%\n', |
| | 403 | '\n\t \t {%\n'), |
| | 404 | # Leading whitespace with text before single template tag |
| | 405 | 'insignificant-whitespace05': ('\n some\ttext {% templatetag openblock %}\n', {}, '\n some\ttext {%\n', |
| | 406 | '\n some\ttext {%\n'), |
| | 407 | # Leading line with text before single template tag |
| | 408 | 'insignificant-whitespace06': ('\n some\ttext\n {% templatetag openblock %}\n', {}, '\n some\ttext{%\n', |
| | 409 | '\n some\ttext\n {%\n'), |
| | 410 | 'insignificant-whitespace07': ('\n some\ttext \n \t {% templatetag openblock %}\n', {}, '\n some\ttext {%\n', |
| | 411 | '\n some\ttext \n \t {%\n'), |
| | 412 | # whitespace leading /before/ the newline is not stripped. |
| | 413 | 'insignificant-whitespace08': ('\n some\ttext \t \n {% templatetag openblock %}\n', {}, '\n some\ttext \t {%\n', |
| | 414 | '\n some\ttext \t \n {%\n'), |
| | 415 | # Multiple text lines before tag |
| | 416 | 'insignificant-whitespace09': ('\n some\ntext \t \n {% templatetag openblock %}\n', {}, '\n some\ntext \t {%\n', |
| | 417 | '\n some\ntext \t \n {%\n'), |
| | 418 | 'insignificant-whitespace10': ('\n some \t \n \t text \t \n {% templatetag openblock %}\n', {}, '\n some \t \n \t text \t {%\n', |
| | 419 | '\n some \t \n \t text \t \n {%\n'), |
| | 420 | # Leading whitespace before tag, some text after |
| | 421 | 'insignificant-whitespace11': ('\n \t {% templatetag openblock %} some text\n', {}, '\n \t {% some text\n', |
| | 422 | '\n \t {% some text\n'), |
| | 423 | # Leading whitespace before tag, some text with trailing whitespace after |
| | 424 | 'insignificant-whitespace12': ('\n \t {% templatetag openblock %} some text \t \n', {}, '\n \t {% some text \t \n', |
| | 425 | '\n \t {% some text \t \n'), |
| | 426 | # Whitespace after tag is not removed |
| | 427 | 'insignificant-whitespace13': ('\n \t {% templatetag openblock %} \t \n \t some text \t \n', {}, '{% \t \n \t some text \t \n', |
| | 428 | '\n \t {% \t \n \t some text \t \n'), |
| | 429 | # Multiple lines of leading whitespace. Only one leading newline is removed |
| | 430 | 'insignificant-whitespace14': ('\n\n\n{% templatetag openblock %}\n some text\n', {}, '\n\n{%\n some text\n', |
| | 431 | '\n\n\n{%\n some text\n'), |
| | 432 | # Trailing whitespace after tag |
| | 433 | 'insignificant-whitespace15': ('\n\n\n{% templatetag openblock %}\t \t \t\n some text\n', {}, '\n\n{%\t \t \t\n some text\n', |
| | 434 | '\n\n\n{%\t \t \t\n some text\n'), |
| | 435 | # Removable newline followed by leading whitespace |
| | 436 | 'insignificant-whitespace16': ('\n\n\n\t \t \t{% templatetag openblock %}\n some text\n', {}, '\n\n{%\n some text\n', |
| | 437 | '\n\n\n\t \t \t{%\n some text\n'), |
| | 438 | # Removable leading whitespace and trailing whitespace |
| | 439 | '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', |
| | 440 | '\n\n\n\t \t \t{%\t \t \t\n some text\n'), |
| | 441 | # Multiple lines of trailing whitespace. No trailing newline is removed. |
| | 442 | 'insignificant-whitespace18': ('\n{% templatetag openblock %}\n\n\n some text\n', {}, '{%\n\n\n some text\n', |
| | 443 | '\n{%\n\n\n some text\n'), |
| | 444 | 'insignificant-whitespace19': ('\n{% templatetag openblock %}\t \n\n\n some text\n', {}, '{%\t \n\n\n some text\n', |
| | 445 | '\n{%\t \n\n\n some text\n'), |
| | 446 | # Consecutive trimmed lines with tags strips one newline each |
| | 447 | 'insignificant-whitespace20': ( |
| | 448 | '\n{% templatetag openblock %}\n{% templatetag openblock %}\n{% templatetag openblock %}\n some text\n' |
| | 449 | , {}, '{%{%{%\n some text\n', |
| | 450 | '\n{%\n{%\n{%\n some text\n'), |
| | 451 | # Consecutive trimmed lines with tags strips one newline each. Intermediate newlines are preserved |
| | 452 | 'insignificant-whitespace21': ( |
| | 453 | '\n\n{% templatetag openblock %}\n\n{% templatetag openblock %}\n\n{% templatetag openblock %}\n\n some text\n' |
| | 454 | , {}, '\n{%\n{%\n{%\n\n some text\n', |
| | 455 | '\n\n{%\n\n{%\n\n{%\n\n some text\n'), |
| | 456 | # Consecutive trimmed lines with tags strips one newline each. Leading whitespace is stripped but trailing is not |
| | 457 | 'insignificant-whitespace22': ( |
| | 458 | '\n\n\t {% templatetag openblock %}\t \n\n\t {% templatetag openblock %}\t \n\n\t {% templatetag openblock %}\t \n some text\n' |
| | 459 | , {}, '\n{%\t \n{%\t \n{%\t \n some text\n', |
| | 460 | '\n\n\t {%\t \n\n\t {%\t \n\n\t {%\t \n some text\n'), |
| | 461 | # Consecutive trimmed lines with tags strips one newline each. Intermediate whitespace is stripped |
| | 462 | 'insignificant-whitespace23': ( |
| | 463 | '\n\t {% templatetag openblock %}\t \n\t {% templatetag openblock %}\t \n\t {% templatetag openblock %}\t \n some text\n' |
| | 464 | , {}, '{%\t {%\t {%\t \n some text\n', |
| | 465 | '\n\t {%\t \n\t {%\t \n\t {%\t \n some text\n'), |
| | 466 | # Intermediate whitespace on one line is preserved |
| | 467 | # Consecutive tags on one line do not have intermediate whitespace or leading whitespace stripped |
| | 468 | 'insignificant-whitespace24': ( |
| | 469 | '\n\t {% templatetag openblock %}\t \t {% templatetag openblock %}\t \t {% templatetag openblock %}\t \n some text\n' |
| | 470 | , {}, '\n\t {%\t \t {%\t \t {%\t \n some text\n', |
| | 471 | '\n\t {%\t \t {%\t \t {%\t \n some text\n'), |
| | 472 | # Still, only one leading newline is removed. |
| | 473 | 'insignificant-whitespace25': ( |
| | 474 | '\n\n {% templatetag openblock %}\n \t {% templatetag openblock %}\n \t {% templatetag openblock %}\n some text\n' |
| | 475 | , {}, '\n{%{%{%\n some text\n', |
| | 476 | '\n\n {%\n \t {%\n \t {%\n some text\n'), |
| | 477 | # Lines with {# comments #} have the same stripping behavior |
| | 478 | 'insignificant-whitespace26': ( |
| | 479 | '\n\n {% templatetag openblock %}\n \t {# some comment #}\n some text\n' |
| | 480 | , {}, '\n{%\n some text\n', |
| | 481 | '\n\n {%\n \t \n some text\n'), |
| | 482 | # Only {# comments #} |
| | 483 | 'insignificant-whitespace27': ( |
| | 484 | '\n\n {# a comment #}\n \t {# some comment #}\n some text\n' |
| | 485 | , {}, '\n\n some text\n', |
| | 486 | '\n\n \n \t \n some text\n'), |
| | 487 | # Consecutive newlines with tags and comments |
| | 488 | 'insignificant-whitespace28': ( |
| | 489 | '\n\t {% templatetag openblock %}\t \n\t {# some comment #}\t \n\t {% templatetag openblock %}\t \n some text\n' |
| | 490 | , {}, '{%\t \t {%\t \n some text\n', |
| | 491 | '\n\t {%\t \n\t \t \n\t {%\t \n some text\n'), |
| | 492 | |
| | 493 | # Lines with only {{ values }} have the same stripping behavior |
| | 494 | 'insignificant-whitespace29': ( |
| | 495 | '\n {% templatetag openblock %}\t\n \t {{ spam }}\t \n \t {% templatetag openblock %}\t \n some text\n' |
| | 496 | , {"spam" : "ham"}, '{%\tham\t {%\t \n some text\n', |
| | 497 | '\n {%\t\n \t ham\t \n \t {%\t \n some text\n'), |
| | 498 | 'insignificant-whitespace30': ( |
| | 499 | '\n\n {% templatetag openblock %}\t\n\n \t {{ spam }}\t \n\n \t {% templatetag openblock %}\t \n some text\n' |
| | 500 | , {"spam" : "ham"}, '\n{%\t\nham\t \n{%\t \n some text\n', |
| | 501 | '\n\n {%\t\n\n \t ham\t \n\n \t {%\t \n some text\n'), |
| | 502 | ## Leading whitespace not stripped when followed by anything. See insignificant-whitespace24 |
| | 503 | 'insignificant-whitespace31': ( |
| | 504 | '\n {% templatetag openblock %}\t \t {{ spam }}\t \t {% templatetag openblock %}\t \n some text\n' |
| | 505 | , {"spam" : "ham"}, '\n {%\t \t ham\t \t {%\t \n some text\n', |
| | 506 | '\n {%\t \t ham\t \t {%\t \n some text\n'), |
| | 507 | # {{ value }} {% tag %} {{ value }} this time |
| | 508 | 'insignificant-whitespace32': ( |
| | 509 | '\n {{ spam }}\t\n \t {% templatetag openblock %}\t \n \t {{ spam }}\t \n some text\n' |
| | 510 | , {"spam" : "ham"}, 'ham\t{%\t ham\t \n some text\n', |
| | 511 | '\n ham\t\n \t {%\t \n \t ham\t \n some text\n'), |
| | 512 | |
| | 513 | # Invalid stuff is still invalid |
| | 514 | # Newlines inside begin-end tokens, even in {# comments #}, make it not a tag. |
| | 515 | 'insignificant-whitespace33': ( |
| | 516 | '\n\n {# \n{% templatetag openblock #}\t \n some text\n' |
| | 517 | , {}, '\n\n {# \n{% templatetag openblock #}\t \n some text\n', |
| | 518 | '\n\n {# \n{% templatetag openblock #}\t \n some text\n'), |
| | 519 | # Complete comment matching tags on one line are processed |
| | 520 | 'insignificant-whitespace34': ( |
| | 521 | '\n\n {# \n{# templatetag openblock #}\t \n some text\n' |
| | 522 | , {}, '\n\n {# \t \n some text\n', |
| | 523 | '\n\n {# \n\t \n some text\n'), |
| | 524 | 'insignificant-whitespace35': ( |
| | 525 | '\n\n {# \n{# templatetag openblock\n #}\t \n some text\n' |
| | 526 | , {}, '\n\n {# \n{# templatetag openblock\n #}\t \n some text\n', |
| | 527 | '\n\n {# \n{# templatetag openblock\n #}\t \n some text\n'), |
| | 528 | 'insignificant-whitespace36': ( |
| | 529 | '\n\n {# \n{{ some comment #}\t \n some text\n' |
| | 530 | , {}, '\n\n {# \n{{ some comment #}\t \n some text\n', |
| | 531 | '\n\n {# \n{{ some comment #}\t \n some text\n'), |
| | 532 | 'insignificant-whitespace37': ( |
| | 533 | '\n\n {# \n \t {% templatetag openblock #}\t \n some text\n' |
| | 534 | , {}, '\n\n {# \n \t {% templatetag openblock #}\t \n some text\n', |
| | 535 | '\n\n {# \n \t {% templatetag openblock #}\t \n some text\n'), |
| | 536 | 'insignificant-whitespace38': ( |
| | 537 | "\n\n {# templatetag openblock #\n}\t \n some text\n" |
| | 538 | , {}, "\n\n {# templatetag openblock #\n}\t \n some text\n", |
| | 539 | "\n\n {# templatetag openblock #\n}\t \n some text\n" ), |
| | 540 | 'insignificant-whitespace39': ( |
| | 541 | "\n\n {% templatetag openblock %\n}\t \n some text\n" |
| | 542 | , {}, "\n\n {% templatetag openblock %\n}\t \n some text\n", |
| | 543 | "\n\n {% templatetag openblock %\n}\t \n some text\n" ), |
| | 544 | 'insignificant-whitespace40': ( |
| | 545 | "\n\n {{ templatetag openblock }\n}\t \n some text\n" |
| | 546 | , {}, "\n\n {{ templatetag openblock }\n}\t \n some text\n", |
| | 547 | "\n\n {{ templatetag openblock }\n}\t \n some text\n" ), |
| | 548 | 'insignificant-whitespace41': ( |
| | 549 | "\n\n {\n# {# templatetag openblock #}\t \n some text\n" |
| | 550 | , {}, "\n\n {\n# \t \n some text\n", |
| | 551 | "\n\n {\n# \t \n some text\n"), |
| | 552 | 'insignificant-whitespace42': ( |
| | 553 | "\n\n {\n {# templatetag openblock #}\t \n some text\n" |
| | 554 | , {}, "\n\n {\t \n some text\n", |
| | 555 | "\n\n {\n \t \n some text\n"), |
| | 556 | 'insignificant-whitespace43': ( |
| | 557 | "\n{{# foo #};{# bar #}\n" |
| | 558 | , {}, "\n{;\n", |
| | 559 | "\n{;\n"), |
| | 560 | } |
| | 561 | tests = whitespace_tests.items() |
| | 562 | tests.sort() |
| | 563 | |
| | 564 | # Register our custom template loader. |
| | 565 | def test_whitespace_loader(template_name, template_dirs=None): |
| | 566 | "A custom template loader that loads the unit-test templates." |
| | 567 | try: |
| | 568 | return (whitespace_tests[template_name][0] , "test:%s" % template_name) |
| | 569 | except KeyError: |
| | 570 | raise template.TemplateDoesNotExist, template_name |
| | 571 | |
| | 572 | old_template_loaders = loader.template_source_loaders |
| | 573 | loader.template_source_loaders = [test_whitespace_loader] |
| | 574 | |
| | 575 | failures = [] |
| | 576 | |
| | 577 | old_strip_leading_whitespace = settings.TEMPLATE_STRIP_LEADING_WHITESPACE |
| | 578 | |
| | 579 | for name, vals in tests: |
| | 580 | for strip_leading_whitespace in (True, False): |
| | 581 | settings.TEMPLATE_STRIP_LEADING_WHITESPACE = strip_leading_whitespace |
| | 582 | test_template = loader.get_template(name) |
| | 583 | result = vals[2] if strip_leading_whitespace else vals[3] |
| | 584 | output = self.render(test_template, vals) |
| | 585 | |
| | 586 | if output != result: |
| | 587 | failures.append("Whitespace test: %s -- FAILED. Expected %r, got %r" % (name, result, output)) |
| | 588 | |
| | 589 | loader.template_source_loaders = old_template_loaders |
| | 590 | settings.TEMPLATE_STRIP_LEADING_WHITESPACE = old_strip_leading_whitespace |
| | 591 | |
| | 592 | self.assertEqual(failures, [], "Tests failed:\n%s\n%s" % |
| | 593 | ('-'*70, ("\n%s\n" % ('-'*70)).join(failures))) |
| | 594 | |