Testing plan wave 0: close two live defects, hard-block outbound sends, gate the prod path #88
2 changed files with 38 additions and 2 deletions
|
|
@ -6,7 +6,7 @@ pages:
|
|||
about:
|
||||
title: "About Thermograph: how the weather grades are calculated"
|
||||
description: >-
|
||||
How Thermograph works: ~45 years of ERA5 climate history, a ±7-day
|
||||
How Thermograph works: ~45 years of ERA5 climate history, a ±7-day
|
||||
seasonal window, and empirical percentiles that grade each day relative to
|
||||
its own location.
|
||||
privacy:
|
||||
|
|
@ -21,7 +21,7 @@ pages:
|
|||
temperatures by month, all-time records, and how today's weather compares
|
||||
to local history.
|
||||
glossary_index:
|
||||
title: "Weather & climate glossary: heat index, feels-like, percentile, and more"
|
||||
title: "Weather & climate glossary: heat index, feels-like, percentile, and more"
|
||||
description: >-
|
||||
Plain-language definitions of weather and climate terms: climate normal,
|
||||
percentile, temperature anomaly, feels-like, heat index, wind chill,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package contentdata
|
|||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
@ -109,3 +110,38 @@ func TestLoadRealContentFiles(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pages.yaml's title/description are interpolated as plain strings into
|
||||
// <title> and <meta name="description"> (base.html.tmpl), so html/template
|
||||
// escapes them. An HTML entity written in the YAML is therefore escaped a
|
||||
// second time and the user sees the literal source: "±7-day" in the
|
||||
// SERP snippet, "Weather & climate glossary" in the browser tab. Both
|
||||
// shipped live until this test existed.
|
||||
//
|
||||
// glossary.yaml's `body` is deliberately NOT checked: it is typed
|
||||
// template.HTML (see glossary_term.html.tmpl) and rendered raw, so entities
|
||||
// and <b> tags there are correct and must stay.
|
||||
func TestRealPagesHaveNoDoubleEscapedEntities(t *testing.T) {
|
||||
dir := filepath.Join("..", "..", "..", "content")
|
||||
if _, err := os.Stat(filepath.Join(dir, "pages.yaml")); err != nil {
|
||||
t.Skipf("real content dir not available: %v", err)
|
||||
}
|
||||
pages, err := LoadPages(dir)
|
||||
if err != nil {
|
||||
t.Fatalf("LoadPages(real): %v", err)
|
||||
}
|
||||
// Named (&), decimal (±) and hex (±) entity forms.
|
||||
entity := regexp.MustCompile(`&([a-zA-Z][a-zA-Z0-9]*|#[0-9]+|#[xX][0-9a-fA-F]+);`)
|
||||
for key, p := range pages {
|
||||
for field, value := range map[string]string{
|
||||
"title": p.Title, "description": p.Description,
|
||||
} {
|
||||
if m := entity.FindString(value); m != "" {
|
||||
t.Errorf("pages.yaml[%s].%s contains the HTML entity %q; "+
|
||||
"write the character literally (this field is escaped at "+
|
||||
"render time, so the entity reaches the user as source)",
|
||||
key, field, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue