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 gallery
4
5import (
6 "context"
7 "fmt"
8 "testing"
9 "time"
10
11 "github.com/chromedp/cdproto/runtime"
12 "github.com/chromedp/chromedp"
13 "github.com/chromedp/chromedp/kb"
14
15 "amadan.net/rastrillo/fiesta"
16 "amadan.net/rastrillo/fiesta/internal/harness"
17)
18
19// TestEveryLanguageIsReachableFromThePhoneIndex: every language in the
20// phone index's display settings menu can be reached by Tab, with
21// scripts, and by scrolling the way a finger would, with scripts and
22// without, at 390px and 320px, left to right and right to left, with
23// anchor positioning and without. The menu is at the top of the index
24// and drops down, and the language list opens in place inside its
25// card, so the long list is the card's to scroll. Then every link is
26// followed once, since reaching a link is not using it.
27//
28// "On screen" is inside documentElement's client box, on a rig that
29// draws its scrollbars: see requireDrawnScrollbar.
30func TestEveryLanguageIsReachableFromThePhoneIndex(t *testing.T) {
31 rig := phoneRig(t, harness.WithScrollbars())
32 ctx, cancel := context.WithTimeout(rig.Context(), 300*time.Second)
33 defer cancel()
34 theme := fiesta.ThemeNames()[0]
35 open := `document.getElementById("ds-prefs").open = true; document.querySelector("#ds-prefs [rst-locale]").open = true; true`
36 for _, scripts := range []bool{true, false} {
37 tab := ctx
38 if !scripts {
39 tab = noScripts(t, ctx)
40 }
41 for _, w := range []int64{390, 320} {
42 for _, locale := range []string{"en", "ar"} {
43 for _, anchored := range []bool{true, false} {
44 where := fmt.Sprintf("%s/%s index at %dpx, scripts %v, anchor positioning %v", theme, locale, w, scripts, anchored)
45 mustRun(t, tab, chromedp.EmulateViewport(w, 700),
46 chromedp.Navigate(rig.Origin+pageAt(theme, locale, "index.html")),
47 chromedp.WaitVisible(`#ds-prefs`, chromedp.ByQuery))
48 if !scripts {
49 requireScriptsOff(t, tab, where)
50 }
51 if !anchored {
52 mustRun(t, tab, chromedp.Evaluate(withoutAnchorPositioning, nil,
53 func(p *runtime.EvaluateParams) *runtime.EvaluateParams { return p.WithAwaitPromise(true) }))
54 }
55 requireAnchorPositioning(t, tab, where, "#ds-prefs > [rst-dropdown-menu]", anchored)
56 requireCoarse(t, tab)
57 requireDrawnScrollbar(t, tab, where)
58 mustRun(t, tab, chromedp.Evaluate(`document.getElementById("ds-prefs").open = true;
59 const d = document.querySelector("#ds-prefs [rst-locale]"); d.open = true; d.querySelector("summary").focus(); true`, nil))
60 for i, code := range Locales {
61 if scripts {
62 var got string
63 // 0.5px slack: layout at a fractional rem size lands a few
64 // hundredths of a pixel past the edge, which no eye and no
65 // finger can tell from on screen.
66 mustRun(t, tab, chromedp.KeyEvent(kb.Tab), chromedp.Evaluate(`(() => { const a = document.activeElement, r = a.getBoundingClientRect();
67 const de = document.documentElement;
68 return r.top >= -0.5 && r.bottom <= de.clientHeight + 0.5 && r.left >= -0.5 && r.right <= de.clientWidth + 0.5 ? a.lang : "off screen: " + a.outerHTML.slice(0, 60); })()`, &got))
69 if got != code {
70 t.Errorf("%s: tab %d is %s, want the %s link on screen", where, i+1, got, code)
71 }
72 }
73 var hit bool
74 mustRun(t, tab, chromedp.Evaluate(fmt.Sprintf(`(() => {
75 const a = document.querySelector('#ds-prefs [rst-dropdown-menu] a[lang=%q]');
76 a.scrollIntoView({block: "nearest", inline: "nearest"});
77 const r = a.getBoundingClientRect();
78 return document.elementFromPoint((r.left + r.right) / 2, (r.top + r.bottom) / 2) === a;
79 })()`, code), &hit))
80 if !hit {
81 t.Errorf("%s: scrolled into view, the %s link is not what a finger at its centre touches", where, code)
82 }
83 }
84 }
85 }
86 }
87 }
88
89 // Each link followed once, at 390px with scripts: a plain
90 // navigation, so the leg polls with until.
91 where := theme + "/en index at 390px, scripts on"
92 for _, code := range Locales {
93 mustRun(t, ctx, chromedp.EmulateViewport(390, 700),
94 chromedp.Navigate(rig.Origin+pageAt(theme, "en", "index.html")),
95 chromedp.WaitVisible(`#ds-prefs`, chromedp.ByQuery),
96 chromedp.Evaluate(open, nil),
97 chromedp.Evaluate(fmt.Sprintf(`document.querySelector('#ds-prefs [rst-dropdown-menu] a[lang=%q]').click(); true`, code), nil))
98 until(t, ctx, where+", landed on "+code, fmt.Sprintf(`document.documentElement.lang === %q && location.pathname === %q`, code, pageAt(theme, code, "index.html")))
99 }
100
101 // With scripts off the link is nothing but its href: one activation
102 // through a real navigation.
103 offWhere := theme + "/en index at 390px, scripts off"
104 off := noScripts(t, ctx)
105 mustRun(t, off, chromedp.EmulateViewport(390, 700),
106 chromedp.Navigate(rig.Origin+pageAt(theme, "en", "index.html")),
107 chromedp.WaitVisible(`#ds-prefs`, chromedp.ByQuery))
108 requireScriptsOff(t, off, offWhere)
109 mustRun(t, off, chromedp.Evaluate(open, nil),
110 chromedp.Evaluate(`document.querySelector('#ds-prefs [rst-dropdown-menu] a[lang="ar"]').click(); true`, nil))
111 until(t, off, offWhere+", landed on ar", fmt.Sprintf(`document.documentElement.lang === "ar" && location.pathname === %q`, pageAt(theme, "ar", "index.html")))
112 requireScriptsOff(t, off, offWhere+", on the ar index")
113}
114