| 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 | |