﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
35727	Add `response.text_content` to responses	Adam Johnson	Jae Hyuck Sa 	"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].
"	New feature	closed	HTTP handling	dev	Normal	fixed			Ready for checkin	1	0	0	0	0	0
