pastes: add display_name field

Authenticated users can tag pastes with a human-readable label
via X-Display-Name header. Supports create, update, remove, and
listing. Max 128 chars, control characters rejected.
This commit is contained in:
Username
2026-02-24 12:55:44 +01:00
parent d44c9c66ab
commit 8ebabfe102
5 changed files with 295 additions and 6 deletions

View File

@@ -333,3 +333,97 @@ class TestPastesSearch:
assert response.status_code == 200
data = json.loads(response.data)
assert data["count"] == 1
class TestPastesDisplayName:
"""Tests for display_name field in paste listing."""
def test_create_with_display_name(self, client, auth_header):
"""Create paste with display_name returns it in response."""
response = client.post(
"/",
data="test content",
content_type="text/plain",
headers={**auth_header, "X-Display-Name": "my notes"},
)
assert response.status_code == 201
data = json.loads(response.data)
assert data["display_name"] == "my notes"
def test_display_name_in_listing(self, client, auth_header):
"""Display name appears in paste listing."""
client.post(
"/",
data="test content",
content_type="text/plain",
headers={**auth_header, "X-Display-Name": "project docs"},
)
response = client.get("/pastes", headers=auth_header)
data = json.loads(response.data)
assert data["count"] == 1
assert data["pastes"][0]["display_name"] == "project docs"
def test_display_name_in_metadata(self, client, auth_header):
"""Display name appears in single-paste GET."""
create = client.post(
"/",
data="test content",
content_type="text/plain",
headers={**auth_header, "X-Display-Name": "readme"},
)
paste_id = json.loads(create.data)["id"]
response = client.get(f"/{paste_id}")
data = json.loads(response.data)
assert data["display_name"] == "readme"
def test_display_name_absent_when_unset(self, client, auth_header):
"""Display name is omitted from response when not set."""
create = client.post(
"/",
data="test content",
content_type="text/plain",
headers=auth_header,
)
paste_id = json.loads(create.data)["id"]
response = client.get(f"/{paste_id}")
data = json.loads(response.data)
assert "display_name" not in data
def test_anonymous_display_name_ignored(self, client):
"""Anonymous user's display_name header is silently ignored."""
create = client.post(
"/",
data="test content",
content_type="text/plain",
headers={"X-Display-Name": "sneaky"},
)
assert create.status_code == 201
data = json.loads(create.data)
assert "display_name" not in data
def test_display_name_too_long(self, client, auth_header):
"""Display name exceeding 128 chars is rejected."""
response = client.post(
"/",
data="test content",
content_type="text/plain",
headers={**auth_header, "X-Display-Name": "a" * 129},
)
assert response.status_code == 400
data = json.loads(response.data)
assert "too long" in data["error"].lower()
def test_display_name_control_chars_rejected(self, client, auth_header):
"""Display name with control characters is rejected."""
response = client.post(
"/",
data="test content",
content_type="text/plain",
headers={**auth_header, "X-Display-Name": "bad\x00name"},
)
assert response.status_code == 400
data = json.loads(response.data)
assert "invalid" in data["error"].lower()