Compare commits
2
Commits
cd45cc2f17
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e4770f870 | ||
|
|
fb1088ceec |
@@ -97,6 +97,19 @@ def create_app(config: dict | None = None) -> Flask:
|
|||||||
if response.mimetype == "text/html":
|
if response.mimetype == "text/html":
|
||||||
response.headers["Cache-Control"] = "no-store, must-revalidate"
|
response.headers["Cache-Control"] = "no-store, must-revalidate"
|
||||||
response.headers["Pragma"] = "no-cache"
|
response.headers["Pragma"] = "no-cache"
|
||||||
|
elif response.mimetype in ("text/css", "application/javascript",
|
||||||
|
"text/javascript"):
|
||||||
|
# The static files must NEVER be reused from a cache.
|
||||||
|
|
||||||
|
# Firefox kept serving a stale stylesheet even with
|
||||||
|
# `no-cache`, which meant the page had the new markup and
|
||||||
|
# the old CSS: the advice was expanded inline in the table
|
||||||
|
# instead of in a pop-out, and the long and short labels
|
||||||
|
# were both showing ("BREWING ADVICEADVICE").
|
||||||
|
|
||||||
|
# `no-store` is the only one that means "do not keep this".
|
||||||
|
response.headers["Cache-Control"] = "no-store, must-revalidate"
|
||||||
|
response.headers["Pragma"] = "no-cache"
|
||||||
return response
|
return response
|
||||||
|
|
||||||
csrf = CSRFProtect(app)
|
csrf = CSRFProtect(app)
|
||||||
|
|||||||
@@ -999,10 +999,21 @@ table.data .comment { color: var(--text-muted); font-size: .84rem; }
|
|||||||
|
|
||||||
/* The script opens and closes the panel, and places it. The CSS only
|
/* The script opens and closes the panel, and places it. The CSS only
|
||||||
decides whether it is shown. */
|
decides whether it is shown. */
|
||||||
|
/* The panel is opened by the script, which removes the `hidden`
|
||||||
|
attribute and adds `is-open`.
|
||||||
|
|
||||||
|
The `hidden` attribute is what makes this fail-safe: if the
|
||||||
|
stylesheet is stale and does not know about `.advice-pop` at all,
|
||||||
|
the panel is STILL hidden, so the advice cannot appear expanded
|
||||||
|
inside the table cell. */
|
||||||
.advice-pop.is-open {
|
.advice-pop.is-open {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.advice-pop[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* On a phone there is no hover, so the trigger is a button the script
|
/* On a phone there is no hover, so the trigger is a button the script
|
||||||
toggles, and the panel is pinned to the middle of the screen so it is
|
toggles, and the panel is pinned to the middle of the screen so it is
|
||||||
readable whatever the table's width. */
|
readable whatever the table's width. */
|
||||||
|
|||||||
@@ -131,6 +131,11 @@
|
|||||||
clearTimeout(closeTimer);
|
clearTimeout(closeTimer);
|
||||||
closeTimer = null;
|
closeTimer = null;
|
||||||
}
|
}
|
||||||
|
/* The `hidden` attribute is removed as well as the
|
||||||
|
class added, so the panel is shown even if the
|
||||||
|
stylesheet is an older one that only knows about
|
||||||
|
the class. */
|
||||||
|
panel.removeAttribute("hidden");
|
||||||
panel.classList.add("is-open");
|
panel.classList.add("is-open");
|
||||||
trigger.setAttribute("aria-expanded", "true");
|
trigger.setAttribute("aria-expanded", "true");
|
||||||
place();
|
place();
|
||||||
@@ -138,6 +143,9 @@
|
|||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
panel.classList.remove("is-open");
|
panel.classList.remove("is-open");
|
||||||
|
/* Put the attribute back, so a stale stylesheet
|
||||||
|
cannot leave the advice expanded in the cell. */
|
||||||
|
panel.setAttribute("hidden", "");
|
||||||
trigger.setAttribute("aria-expanded", "false");
|
trigger.setAttribute("aria-expanded", "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,7 +126,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<div class="advice-pop" role="tooltip">
|
<div class="advice-pop" role="tooltip" hidden>
|
||||||
<div class="advice-pop__head">
|
<div class="advice-pop__head">
|
||||||
<span class="advice__label">Brewing advice</span>
|
<span class="advice__label">Brewing advice</span>
|
||||||
<button type="button" class="advice-pop__close"
|
<button type="button" class="advice-pop__close"
|
||||||
|
|||||||
@@ -1162,6 +1162,29 @@ def test_stale_advice_cannot_overwrite_a_comment_edited_outside_the_app(repo):
|
|||||||
assert doc["comment"] == "edited outside the app"
|
assert doc["comment"] == "edited outside the app"
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_advice_pop_out_is_hidden_in_the_markup(client, repo):
|
||||||
|
"""The pop-out carries the `hidden` attribute.
|
||||||
|
|
||||||
|
A stale stylesheet - one that does not know about `.advice-pop` at
|
||||||
|
all - would otherwise leave the advice expanded inline in the table
|
||||||
|
cell, running down the column and off the screen. The `hidden`
|
||||||
|
attribute makes the markup fail-safe: the panel stays hidden until
|
||||||
|
the script opens it.
|
||||||
|
"""
|
||||||
|
repo.users.insert_one({"username": "beer", "password": "beer_pass"})
|
||||||
|
client.post("/login", data={"username": "beer", "password": "beer_pass"},
|
||||||
|
follow_redirects=True)
|
||||||
|
|
||||||
|
seed_readings(repo, [("1", "Ale", "1042", "2026-01-01", False, "")])
|
||||||
|
doc = repo.readings.find_one({"beer_run_id": "1"})
|
||||||
|
repo.set_reading_advice(str(doc["_id"]), "Warm it to 21C and wait.", ok=True)
|
||||||
|
|
||||||
|
body = client.get("/brews").get_data(as_text=True)
|
||||||
|
|
||||||
|
assert 'class="advice-pop"' in body
|
||||||
|
assert 'hidden' in body.split('class="advice-pop"')[1][:60]
|
||||||
|
|
||||||
|
|
||||||
def test_a_failed_advice_is_marked_as_such(client, repo):
|
def test_a_failed_advice_is_marked_as_such(client, repo):
|
||||||
"""A generation failure reads differently from real advice."""
|
"""A generation failure reads differently from real advice."""
|
||||||
repo.users.insert_one({"username": "beer", "password": "beer_pass"})
|
repo.users.insert_one({"username": "beer", "password": "beer_pass"})
|
||||||
|
|||||||
Reference in New Issue
Block a user