#35727: Add `response.text_content` to responses
------------------------------+-----------------------------------------
     Reporter:  Adam Johnson  |                     Type:  New feature
       Status:  new           |                Component:  HTTP handling
      Version:  dev           |                 Severity:  Normal
     Keywords:                |             Triage Stage:  Unreviewed
    Has patch:  0             |      Needs documentation:  0
  Needs tests:  0             |  Patch needs improvement:  0
Easy pickings:  0             |                    UI/UX:  0
------------------------------+-----------------------------------------
 A common pattern in tests is to make assertions on the response content.
 [https://docs.djangoproject.com/en/stable/ref/request-
 response/#django.http.HttpResponse.content HttpResponse.content] is
 `bytes`, requiring a call to `.decode()` for assertions with `str` values:

 {{{
 class DiggerLogTests(TestCase):
     def test_get(self):
         response = self.client.get('/digger/logs')
         assert 'Good digging' in response.content.decode()
         assert '2022-01-01 12:00:00' in response.content.decode()
 }}}

 This is suboptimal for a few reasons:

 * It requires extra code.
 * Mixed bytes/str errors may confuse beginners.
 * `decode()` imparts a small but measurable overhead, especially if
 repeated for each assertion as above.
 * `.decode()` defaults to UTF-8. Whilst this is by far the most common
 encoding, the response may actually use a different encoding, as per
 [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
 the content-type header].

 I propose that responses from the test client include a new attribute,
 called `text_content`. This would be cached property returning `content`
 decoded into a `str`, per any `charset` in `content-type`.

 This new attribute would allow the above test to be written as:

 {{{
 class DiggerLogTests(TestCase):
     def test_get(self):
         response = self.client.get('/digger/logs')
         assert 'Good digging' in response.text
         assert '2022-01-01 12:00:00' in response.text
 }}}

 `text_content` could be added either in `HttpResponse` directly or
 attached by the test client, like `response.json()`. I favour the first
 option a little more as it may come in useful outside of tests, and the
 cache invalidation when `content` is mutated would be easier.

 The new attribute could also be used to simplify `assertContains`,
 
[https://github.com/django/django/blob/387475c5b2f1aa32103dbe21cb281d3b35165a0c/django/test/testcases.py#L586
 which decodes on every call]

 I have wanted this for a while and Simon Willison suggested this feature
 [https://x.com/simonw/status/1728104536898957425 to me on Twitter].
-- 
Ticket URL: <https://code.djangoproject.com/ticket/35727>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/01070191b2f391c1-45af369f-a179-43ca-a33a-f3c1bd66f422-000000%40eu-central-1.amazonses.com.

Reply via email to