| 1 | //go:build browser |
| 2 | |
| 3 | package gallery |
| 4 | |
| 5 | import ( |
| 6 | "context" |
| 7 | "net/http" |
| 8 | "testing" |
| 9 | "time" |
| 10 | |
| 11 | "github.com/chromedp/chromedp" |
| 12 | |
| 13 | "amadan.net/rastrillo/fiesta" |
| 14 | "amadan.net/rastrillo/fiesta/internal/harness" |
| 15 | ) |
| 16 | |
| 17 | // A section that moved pages. A fragment that names nothing on this |
| 18 | // page is looked up in the rail, which links every section on every |
| 19 | // page, and followed by location.replace to the page that has it. Two |
| 20 | // lookups: a rail link whose fragment is the one asked for (an icon |
| 21 | // asked of the Tokens page), and, Fiesta's own, a rail link whose page |
| 22 | // stem is the fragment (#button on a page that is not button.html, |
| 23 | // which is where part 3 kept the button). |
| 24 | |
| 25 | // TestAMovedSectionsOldLinkReachesIt: index.html#button lands on |
| 26 | // button.html and tokens.html#icon-check on icons.html#icon-check with |
| 27 | // the icon on screen, each replacing rather than pushing the address. |
| 28 | // A fragment that is on the page, one the rail does not know, and the |
| 29 | // skip link's target are left alone. |
| 30 | func TestAMovedSectionsOldLinkReachesIt(t *testing.T) { |
| 31 | rig := harness.New(t, func(string) http.Handler { return treeHandler(t) }) |
| 32 | ctx, cancel := context.WithTimeout(rig.Context(), 60*time.Second) |
| 33 | defer cancel() |
| 34 | theme := fiesta.ThemeNames()[0] |
| 35 | index := rig.Origin + pageAt(theme, "en", "index.html") |
| 36 | tokens := rig.Origin + pageAt(theme, "en", "tokens.html") |
| 37 | |
| 38 | start := time.Now() |
| 39 | where := "index.html#button" |
| 40 | mustRun(t, ctx, chromedp.EmulateViewport(1280, 900), chromedp.Navigate(index+"#button"), chromedp.WaitReady("body")) |
| 41 | present(t, ctx, where, "#ds-nav") |
| 42 | until(t, ctx, where, `location.pathname.endsWith("/button.html") && location.hash === "" && document.readyState === "complete"`) |
| 43 | var depth int |
| 44 | mustRun(t, ctx, chromedp.Evaluate(`history.length`, &depth)) |
| 45 | if depth != 2 { |
| 46 | t.Errorf("%s: history is %d deep after the redirect, want 2 (about:blank, then the page); the old address was pushed rather than replaced", where, depth) |
| 47 | } |
| 48 | settle := 2*time.Since(start) + time.Second |
| 49 | |
| 50 | where = "tokens.html#icon-check" |
| 51 | mustRun(t, ctx, chromedp.Navigate(tokens+"#icon-check")) |
| 52 | until(t, ctx, where, `location.pathname.endsWith("/icons.html") && location.hash === "#icon-check" && document.readyState === "complete" && (() => { const r = document.getElementById("icon-check").getBoundingClientRect(); return r.top >= 0 && r.top < innerHeight; })()`) |
| 53 | |
| 54 | for _, c := range []struct{ hash, want string }{ |
| 55 | {"#tokens-accent", "a group that is on Tokens"}, |
| 56 | {"#nope", "a fragment the rail does not know"}, |
| 57 | {"#main", "the skip link's target, which is not a section"}, |
| 58 | } { |
| 59 | where := "tokens.html" + c.hash + ", " + c.want |
| 60 | mustRun(t, ctx, chromedp.Navigate(tokens+c.hash)) |
| 61 | until(t, ctx, where, `document.readyState === "complete"`) |
| 62 | time.Sleep(settle) |
| 63 | var href string |
| 64 | mustRun(t, ctx, chromedp.Evaluate(`location.href`, &href)) |
| 65 | if href != tokens+c.hash { |
| 66 | t.Errorf("%s: the page moved to %s; %s is left alone", where, href, c.want) |
| 67 | } |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | // TestAMovedSectionsOldLinkReachesItFromAnOpenPage: the same old link |
| 72 | // followed with the page already open. Only the fragment changes, so |
| 73 | // nothing is loaded and readiness never fires again; the lookup has to |
| 74 | // run on hashchange too. |
| 75 | func TestAMovedSectionsOldLinkReachesItFromAnOpenPage(t *testing.T) { |
| 76 | rig := harness.New(t, func(string) http.Handler { return treeHandler(t) }) |
| 77 | ctx, cancel := context.WithTimeout(rig.Context(), 60*time.Second) |
| 78 | defer cancel() |
| 79 | theme := fiesta.ThemeNames()[0] |
| 80 | where := "tokens.html open, then #icon-check" |
| 81 | mustRun(t, ctx, chromedp.EmulateViewport(1280, 900), chromedp.Navigate(rig.Origin+pageAt(theme, "en", "tokens.html")), chromedp.WaitReady("body")) |
| 82 | present(t, ctx, where, "#ds-nav") |
| 83 | until(t, ctx, where+", Tokens loaded", `document.readyState === "complete"`) |
| 84 | mustRun(t, ctx, chromedp.Evaluate(`location.hash = "#icon-check"; true`, nil)) |
| 85 | until(t, ctx, where, `location.pathname.endsWith("/icons.html") && location.hash === "#icon-check" && document.readyState === "complete" && (() => { const r = document.getElementById("icon-check").getBoundingClientRect(); return r.top >= 0 && r.top < innerHeight; })()`) |
| 86 | } |
| 87 | |