Skip to content
quarry Artifact [1c5e428f53]
Login

Artifact [1c5e428f53]

Artifact 1c5e428f5381fb97a1871e609c40cba77eb53de8a4cf81eb69376aec6bf6ea35:


package web

import (
	"context"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"craftdesign.group/quarry/internal/ops"
)

type dashFeedIn struct {
	Kind   string `json:"kind"`
	Find   string `json:"find"`
	Repo   string `json:"repo"`
	Offset int    `json:"offset"`
}

type dashAcrossIn struct {
	Awaiting bool `json:"awaiting"`
	Limit    int  `json:"limit"`
}

// The home page is a frame that streams its content, so it never waits
// on the trackers; and the waiting-on-you band, which reaches into every
// tracker the reader can see, is asked for only under ticket changes,
// the one chip that draws it. Computed under every chip and before the
// page could arrive, it cost the home page four seconds whenever those
// trackers were cold.
func TestTheHomeAsksForTheWaitingBandOnlyWhereItIsDrawn(t *testing.T) {
	r := ops.NewRegistry()
	across := 0
	type empty struct{}
	must := func(err error) {
		t.Helper()
		if err != nil {
			t.Fatal(err)
		}
	}
	must(ops.Register(r, ops.Op[dashFeedIn, struct {
		Total int `json:"total"`
	}]{Name: "me.feed", Doc: "test double", Kind: ops.Query, Auth: ops.Token, Route: "GET /api/v1/me/feed",
		Run: func(context.Context, dashFeedIn) (struct {
			Total int `json:"total"`
		}, error) {
			return struct {
				Total int `json:"total"`
			}{}, nil
		}}))
	must(ops.Register(r, ops.Op[dashAcrossIn, struct {
		Tickets []struct{} `json:"tickets"`
	}]{Name: "ticket.across", Doc: "test double", Kind: ops.Query, Auth: ops.Token, Route: "GET /api/v1/me/tickets",
		Run: func(context.Context, dashAcrossIn) (struct {
			Tickets []struct{} `json:"tickets"`
		}, error) {
			across++
			return struct {
				Tickets []struct{} `json:"tickets"`
			}{}, nil
		}}))
	must(ops.Register(r, ops.Op[empty, struct {
		Version string `json:"version"`
	}]{Name: "meta.version", Doc: "test double", Kind: ops.Query, Auth: ops.Anonymous, Route: "GET /api/v1/version",
		Run: func(context.Context, empty) (struct {
			Version string `json:"version"`
		}, error) {
			return struct {
				Version string `json:"version"`
			}{"t"}, nil
		}}))
	h := HandlerWith(r, nil, nil, []Option{WithSessions(fakeSessions{user: "jan", roles: map[string]ops.Auth{"": ops.Token}})})
	get := func(path string) (int, string) {
		req := httptest.NewRequest("GET", path, nil)
		req.AddCookie(&http.Cookie{Name: sessionCookie, Value: "good"})
		w := httptest.NewRecorder()
		h.ServeHTTP(w, req)
		if w.Code != http.StatusOK {
			t.Fatalf("%s: %d", path, w.Code)
		}
		return across, w.Body.String()
	}
	// The page is its frame: it asks for nothing and names where its
	// content comes from, keeping the reader's query.
	n, body := get("/?kind=t")
	if n != 0 || !strings.Contains(body, `data-hook="dash-frame"`) || !strings.Contains(body, `data-init="@get('/?frag=all&kind=t')"`) {
		t.Fatalf("FAIL: the page waited for its content (asked %d), or does not stream it", n)
	}
	for _, path := range []string{"/?frag=all", "/?frag=all&kind=c", "/?frag=all&kind=w"} {
		if n, body := get(path); n != 0 || !strings.Contains(body, `id="dash-feed"`) {
			t.Errorf("FAIL: %s asked for the waiting band (%d), or brought no feed", path, n)
		}
	}
	if n, _ := get("/?frag=all&kind=t"); n != 1 {
		t.Errorf("FAIL: ticket changes did not ask for its band (%d)", n)
	}
}

// homeContent is the home page's content URL for path: the page itself
// is a frame, and what fills it is ?frag=all with the same query.
func homeContent(path string) string {
	if !strings.HasPrefix(path, "/") || strings.HasPrefix(path, "/?view=explore") {
		return path
	}
	rest := strings.TrimPrefix(strings.TrimPrefix(path, "/"), "?")
	if path != "/" && !strings.HasPrefix(path, "/?") {
		return path
	}
	if rest == "" {
		return "/?frag=all"
	}
	return "/?frag=all&" + rest
}

// unpatch is a Datastar element patch read back as the HTML it carries,
// so a test reads the streamed content as it would the page.
func unpatch(body string) string {
	if !strings.HasPrefix(body, "event: datastar-patch-elements") {
		return body
	}
	var out []string
	for _, l := range strings.Split(body, "\n") {
		if rest, ok := strings.CutPrefix(l, "data: elements "); ok {
			out = append(out, rest)
		}
	}
	return strings.Join(out, "\n")
}