| 1 | package movementtest |
| 2 | |
| 3 | import ( |
| 4 | "net/http" |
| 5 | "strings" |
| 6 | "testing" |
| 7 | |
| 8 | movement "amadan.net/carlos/movement/internal/movement" |
| 9 | ) |
| 10 | |
| 11 | // Links live beside the copy rather than inside it, matched by phrase. That |
| 12 | // keeps markup out of the copy table, and it means a rewrite can silently |
| 13 | // orphan a link by rewording around its phrase. Nothing would look broken — |
| 14 | // the paragraph would just quietly stop linking — so it is checked here. |
| 15 | func TestEveryLinkPhraseStillAppearsInItsCopy(t *testing.T) { |
| 16 | for _, id := range []string{"index.lede"} { |
| 17 | body := strings.Join(movement.Paragraphs(id), " ") |
| 18 | for _, phrase := range movement.LinkPhrases(id) { |
| 19 | if !strings.Contains(body, phrase) { |
| 20 | t.Errorf("%s links the phrase %q, which the copy no longer "+ |
| 21 | "contains — the link has been orphaned by a rewrite", id, phrase) |
| 22 | } |
| 23 | } |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | func TestLedeLinksRenderAndOpenInANewTab(t *testing.T) { |
| 28 | h := newApp(t) |
| 29 | body := get(t, h, "/").Body.String() |
| 30 | |
| 31 | for _, want := range []string{ |
| 32 | `href="https://11factor.org"`, |
| 33 | `href="https://carlosframework.com/"`, |
| 34 | } { |
| 35 | if !strings.Contains(body, want) { |
| 36 | t.Errorf("the lede is missing %s", want) |
| 37 | } |
| 38 | } |
| 39 | // Every outbound link leaves in its own tab, and carries the rel that |
| 40 | // stops the new page reaching back into this one. |
| 41 | if strings.Count(body, `rel="noopener noreferrer"`) < 3 { |
| 42 | t.Error("an outbound link is missing target/rel") |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | // The copy is escaped before any anchor is spliced in, so nothing written in |
| 47 | // the copy table can become markup. |
| 48 | func TestLedeCopyCannotBecomeMarkup(t *testing.T) { |
| 49 | h := newApp(t) |
| 50 | rec := get(t, h, "/") |
| 51 | if rec.Code != http.StatusOK { |
| 52 | t.Fatalf("GET /: %d", rec.Code) |
| 53 | } |
| 54 | body := rec.Body.String() |
| 55 | |
| 56 | // The apostrophes in the copy must arrive escaped, which is the visible |
| 57 | // proof that escaping ran before the links went in. |
| 58 | if strings.Contains(body, "We’ve built") && !strings.Contains(body, "'") && |
| 59 | !strings.Contains(body, "’") { |
| 60 | t.Error("copy reached the page without passing through escaping") |
| 61 | } |
| 62 | } |
| 63 | |