//go:build browser package gallery import ( "context" "net/http" "testing" "time" "github.com/chromedp/chromedp" "amadan.net/rastrillo/fiesta" "amadan.net/rastrillo/fiesta/internal/harness" ) // A section that moved pages. A fragment that names nothing on this // page is looked up in the rail, which links every section on every // page, and followed by location.replace to the page that has it. Two // lookups: a rail link whose fragment is the one asked for (an icon // asked of the Tokens page), and, Fiesta's own, a rail link whose page // stem is the fragment (#button on a page that is not button.html, // which is where part 3 kept the button). // TestAMovedSectionsOldLinkReachesIt: index.html#button lands on // button.html and tokens.html#icon-check on icons.html#icon-check with // the icon on screen, each replacing rather than pushing the address. // A fragment that is on the page, one the rail does not know, and the // skip link's target are left alone. func TestAMovedSectionsOldLinkReachesIt(t *testing.T) { rig := harness.New(t, func(string) http.Handler { return treeHandler(t) }) ctx, cancel := context.WithTimeout(rig.Context(), 60*time.Second) defer cancel() theme := fiesta.ThemeNames()[0] index := rig.Origin + pageAt(theme, "en", "index.html") tokens := rig.Origin + pageAt(theme, "en", "tokens.html") start := time.Now() where := "index.html#button" mustRun(t, ctx, chromedp.EmulateViewport(1280, 900), chromedp.Navigate(index+"#button"), chromedp.WaitReady("body")) present(t, ctx, where, "#ds-nav") until(t, ctx, where, `location.pathname.endsWith("/button.html") && location.hash === "" && document.readyState === "complete"`) var depth int mustRun(t, ctx, chromedp.Evaluate(`history.length`, &depth)) if depth != 2 { 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) } settle := 2*time.Since(start) + time.Second where = "tokens.html#icon-check" mustRun(t, ctx, chromedp.Navigate(tokens+"#icon-check")) 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; })()`) for _, c := range []struct{ hash, want string }{ {"#tokens-accent", "a group that is on Tokens"}, {"#nope", "a fragment the rail does not know"}, {"#main", "the skip link's target, which is not a section"}, } { where := "tokens.html" + c.hash + ", " + c.want mustRun(t, ctx, chromedp.Navigate(tokens+c.hash)) until(t, ctx, where, `document.readyState === "complete"`) time.Sleep(settle) var href string mustRun(t, ctx, chromedp.Evaluate(`location.href`, &href)) if href != tokens+c.hash { t.Errorf("%s: the page moved to %s; %s is left alone", where, href, c.want) } } } // TestAMovedSectionsOldLinkReachesItFromAnOpenPage: the same old link // followed with the page already open. Only the fragment changes, so // nothing is loaded and readiness never fires again; the lookup has to // run on hashchange too. func TestAMovedSectionsOldLinkReachesItFromAnOpenPage(t *testing.T) { rig := harness.New(t, func(string) http.Handler { return treeHandler(t) }) ctx, cancel := context.WithTimeout(rig.Context(), 60*time.Second) defer cancel() theme := fiesta.ThemeNames()[0] where := "tokens.html open, then #icon-check" mustRun(t, ctx, chromedp.EmulateViewport(1280, 900), chromedp.Navigate(rig.Origin+pageAt(theme, "en", "tokens.html")), chromedp.WaitReady("body")) present(t, ctx, where, "#ds-nav") until(t, ctx, where+", Tokens loaded", `document.readyState === "complete"`) mustRun(t, ctx, chromedp.Evaluate(`location.hash = "#icon-check"; true`, nil)) 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; })()`) }