fix: Extract mp-slug before property normalization
Fix bug where custom slugs (mp-slug) were being ignored because they were extracted from normalized properties after being filtered out. The root cause: normalize_properties() filters out all mp-* parameters (line 139) because they're Micropub server extensions, not properties. The old code tried to extract mp-slug from the normalized properties dict, but it had already been removed. The fix: Extract mp-slug directly from raw request data BEFORE calling normalize_properties(). This preserves the custom slug through to create_note(). Changes: - Move mp-slug extraction to before property normalization (line 290-299) - Handle both form-encoded (list) and JSON (string or list) formats - Add comprehensive tests for custom slug with both request formats - All 13 Micropub tests pass Fixes the issue reported in production where Quill-specified slugs were being replaced with auto-generated ones. References: - docs/reports/custom-slug-bug-diagnosis.md (architect's analysis) - Micropub spec: mp-slug is a server extension parameter Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -188,6 +188,64 @@ def test_micropub_create_with_categories(client, app, mock_valid_token):
|
||||
assert 'Location' in response.headers
|
||||
|
||||
|
||||
def test_micropub_create_with_custom_slug_form(client, app, mock_valid_token):
|
||||
"""Test creating a note with custom slug via form-encoded request"""
|
||||
with patch('starpunk.routes.micropub.verify_external_token', mock_valid_token):
|
||||
response = client.post(
|
||||
'/micropub',
|
||||
data={
|
||||
'h': 'entry',
|
||||
'content': 'This is a test for custom slugs',
|
||||
'mp-slug': 'my-custom-slug'
|
||||
},
|
||||
headers={'Authorization': 'Bearer valid_token'}
|
||||
)
|
||||
|
||||
assert response.status_code == 201
|
||||
assert 'Location' in response.headers
|
||||
|
||||
# Verify the custom slug was used
|
||||
location = response.headers['Location']
|
||||
assert location.endswith('/notes/my-custom-slug')
|
||||
|
||||
# Verify note exists with the custom slug
|
||||
with app.app_context():
|
||||
note = get_note('my-custom-slug')
|
||||
assert note is not None
|
||||
assert note.slug == 'my-custom-slug'
|
||||
assert note.content == 'This is a test for custom slugs'
|
||||
|
||||
|
||||
def test_micropub_create_with_custom_slug_json(client, app, mock_valid_token):
|
||||
"""Test creating a note with custom slug via JSON request"""
|
||||
with patch('starpunk.routes.micropub.verify_external_token', mock_valid_token):
|
||||
response = client.post(
|
||||
'/micropub',
|
||||
json={
|
||||
'type': ['h-entry'],
|
||||
'properties': {
|
||||
'content': ['JSON test with custom slug']
|
||||
},
|
||||
'mp-slug': 'json-custom-slug'
|
||||
},
|
||||
headers={'Authorization': 'Bearer valid_token'}
|
||||
)
|
||||
|
||||
assert response.status_code == 201
|
||||
assert 'Location' in response.headers
|
||||
|
||||
# Verify the custom slug was used
|
||||
location = response.headers['Location']
|
||||
assert location.endswith('/notes/json-custom-slug')
|
||||
|
||||
# Verify note exists with the custom slug
|
||||
with app.app_context():
|
||||
note = get_note('json-custom-slug')
|
||||
assert note is not None
|
||||
assert note.slug == 'json-custom-slug'
|
||||
assert note.content == 'JSON test with custom slug'
|
||||
|
||||
|
||||
# Query Tests
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user