rastrillo / fiesta Public

Clone
git clone https://amadan.net/rastrillo/fiesta

Plain git — no account needed to clone.

Download

Download this file

1//go:build browser
2
3package harness
4
5import (
6 "fmt"
7 "net/http"
8 "strings"
9 "testing"
10
11 "github.com/chromedp/chromedp"
12)
13
14func staticPage(body string) func(string) http.Handler {
15 return func(string) http.Handler {
16 mux := http.NewServeMux()
17 mux.HandleFunc("GET /{$}", func(w http.ResponseWriter, req *http.Request) {
18 w.Header().Set("Content-Type", "text/html; charset=utf-8")
19 fmt.Fprintf(w, `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>junk</title></head><body>%s</body></html>`, body)
20 })
21 return mux
22 }
23}
24
25// The three places junk hides: rendered text, an input's value, and
26// the label a screen reader announces — each hit shown with its
27// surroundings, so a prose false-positive is legible at a glance.
28func TestJunkScanReadsTextInputsAndARIA(t *testing.T) {
29 r := New(t, staticPage(`<main id="app">
30<p>the price is undefined today</p>
31<input value="[object Object]">
32<button aria-label="null">x</button>
33</main>`))
34 r.Run(chromedp.Navigate(r.Origin+"/"), chromedp.WaitVisible("#app", chromedp.ByQuery))
35 hits := r.junkHits("#app")
36 joined := strings.Join(hits, "\n")
37 for _, want := range []string{
38 `undefined in: "the price is undefined today`,
39 "[object Object]",
40 "null",
41 } {
42 if !strings.Contains(joined, want) {
43 t.Errorf("scan missed %q:\n%s", want, joined)
44 }
45 }
46 if len(hits) != 3 {
47 t.Errorf("want 3 hits, got %d:\n%s", len(hits), joined)
48 }
49}
50
51// AllowText spares deliberate prose; the junk value stays banned
52// everywhere else on the screen.
53func TestAllowTextSparesDeliberateProse(t *testing.T) {
54 r := New(t, staticPage(`<main id="app"><p>this contract is null and void</p></main>`))
55 r.AllowText("null and void")
56 r.Run(chromedp.Navigate(r.Origin+"/"), chromedp.WaitVisible("#app", chromedp.ByQuery))
57 if hits := r.junkHits("#app"); len(hits) > 0 {
58 t.Errorf("allowed prose still hit: %v", hits)
59 }
60 r.Screen("#app", "the prose screen") // and the full gate passes too
61}
62
63// A missing scan root is itself a finding, never a silent pass.
64func TestJunkScanReportsAMissingRoot(t *testing.T) {
65 r := New(t, staticPage(`<p id="up">no app root here</p>`))
66 r.Run(chromedp.Navigate(r.Origin+"/"), chromedp.WaitVisible("#up", chromedp.ByQuery))
67 hits := r.junkHits("#app")
68 if len(hits) != 1 || !strings.Contains(hits[0], "#app") {
69 t.Errorf("missing root not reported: %v", hits)
70 }
71}
72
73// The whole gate, green on a clean page: wait, scan, flush.
74func TestScreenPassesACleanPage(t *testing.T) {
75 r := New(t, staticPage(`<main id="app"><h1>all well</h1></main>`))
76 r.Run(chromedp.Navigate(r.Origin + "/"))
77 r.Screen("#app", "clean page")
78}
79