fix: deleted image wrongfully caching

This commit is contained in:
fsylvain committed 2026-10-01 05:27:25 +02:00
1 parent b3793d5dbb
commit ff0854f331
19 files changed
+201 -87

No files matched your search

+6 -6
View File
@@ -59,9 +59,9 @@ Feature: Articles list screen
remaining articles, and raises an info toast (icon info, id "article-not-found-{id}"): title
"That article no longer exists" text "It was deleted somewhere else, so we removed it from
the list."
And "Delete…" opens ConfirmDialog: title "Delete this article?" text "\"{title}\" and its
{n} images will be deleted. This can't be undone." (a components.md convention: the row's
title plus its image count, "and its image" for exactly 1 and no image clause at all for 0),
And "Delete…" opens ConfirmDialog: title "Delete this article?" text "\"{title}\" will be
deleted. Its images stay in your library. This can't be undone." (the second sentence is
present only when the article body holds at least one image),
"Cancel" and "Delete article" (danger); while the DELETE request is in flight the dialog
cannot be dismissed by Cancel, Esc or a backdrop click, both buttons are disabled, the
confirm button reads "Deleting…" with a loading indicator, and aria-busy is set
@@ -72,7 +72,7 @@ Feature: Articles list screen
And a successful delete (204) closes the dialog, removes the row, moves focus to the next row
(or the page heading if the deleted row was last), recomputes the tab counts, and raises a
success toast (icon circle-check, id "article-deleted-{id}"): title "Article deleted" text
"\"{title}\" and its images are gone."; this is also where a delete initiated from the editor
"\"{title}\" is gone."; this is also where a delete initiated from the editor
ends up
And the list, sorted by last updated with the most recently updated article first, holds
these 6 articles by default: id 1 "How we price a bathroom renovation" (online, updated "2
@@ -231,7 +231,7 @@ Feature: Articles list screen
Given the Default state has loaded, and id 4 "Winter checklist for timber windows" has 3 images
When the user chooses "Delete…" from id 4's row menu
Then ConfirmDialog opens: title "Delete this article?" text "\"Winter checklist for timber
windows\" and its 3 images will be deleted. This can't be undone.", "Cancel" and "Delete
windows\" will be deleted. Its images stay in your library. This can't be undone.", "Cancel" and "Delete
article" (danger)
Scenario: Delete in progress — the dialog cannot be dismissed while the request is in flight
@@ -256,4 +256,4 @@ Feature: Articles list screen
Then the dialog closes, id 4's row is removed from the list, and focus moves to the next row
And the tabs read "All 5" "Online 4" "Drafts 1"
And a success toast appears: icon circle-check, id "article-deleted-4", title "Article
deleted", text "\"Winter checklist for timber windows\" and its images are gone."
deleted", text "\"Winter checklist for timber windows\" is gone."
+1 -1
View File
@@ -114,7 +114,7 @@ as listed), unless a scenario's Examples row substitutes a smaller fixture.
18. **Deleted** — continuing from 16 (a fresh attempt), resolve the DELETE 204; assert the dialog
closes, id 4's row is removed, focus moves to the next row; assert tabs read "All 5" "Online
4" "Drafts 1"; assert a toast with id "article-deleted-4", icon circle-check, title "Article
deleted", text "\"Winter checklist for timber windows\" and its images are gone."
deleted", text "\"Winter checklist for timber windows\" is gone."
## Visual (manual verification — desktop and mobile, light and dark)
+8 -6
View File
@@ -23,9 +23,11 @@ Feature: Serving uploaded images as static files
"application/octet-stream"
And every response from this handler, success or 404, sets
"X-Content-Type-Options: nosniff"
And every successful response sets a long-lived, public Cache-Control
header, e.g. "public, max-age=31536000, immutable", because a stored
filename is a UUID and its bytes never change
And every successful response sets the Cache-Control header
"public, no-cache", so a browser may store the file but must revalidate
it before reusing it; a stored filename is a UUID and its bytes never
change, but the file can be deleted from the media library, and a
long-lived cache would keep showing it
And an "image/svg+xml" response additionally sets
"Content-Security-Policy: default-src 'none'; style-src
'unsafe-inline'; sandbox", so a script embedded in an uploaded SVG
@@ -42,7 +44,7 @@ Feature: Serving uploaded images as static files
cookie
Then the response status is 200
And the response Content-Type is <content_type>
And the response Cache-Control is "public, max-age=31536000, immutable"
And the response Cache-Control is "public, no-cache"
And the response X-Content-Type-Options is "nosniff"
And the response has no Content-Security-Policy header
And the response body is that file's exact content
@@ -61,7 +63,7 @@ Feature: Serving uploaded images as static files
with no jwt cookie
Then the response status is 200
And the response Content-Type is "image/svg+xml"
And the response Cache-Control is "public, max-age=31536000, immutable"
And the response Cache-Control is "public, no-cache"
And the response X-Content-Type-Options is "nosniff"
And the response Content-Security-Policy is
"default-src 'none'; style-src 'unsafe-inline'; sandbox"
@@ -128,7 +130,7 @@ Feature: Serving uploaded images as static files
with no jwt cookie
Then the response status is 200
And the response Content-Type is "image/webp"
And the response Cache-Control is "public, max-age=31536000, immutable"
And the response Cache-Control is "public, no-cache"
And the response X-Content-Type-Options is "nosniff"
And the response body is empty
+1 -1
View File
@@ -29,7 +29,7 @@ Package: `test` (black-box, new file `test/serve_uploaded_images_test.go`).
non-empty byte content. For each, `httptest.NewRequest("GET",
"/static/uploadedImages/"+name, nil)`, no cookie. Assert status `200`;
`Content-Type` equals the expected value; `Cache-Control` equals
`"public, max-age=31536000, immutable"`; `X-Content-Type-Options` equals
`"public, no-cache"`; `X-Content-Type-Options` equals
`"nosniff"`; `Content-Security-Policy` header is absent; body bytes equal
what was written.
7. Write a `.svg` file whose content contains an inline `onload` handler