Skip to content
quarry Artifact [7f01b73460]
Login

Artifact [7f01b73460]

Artifact 7f01b734600e9db0b0ddfece90934a7c2f88f89e7c9d7a18b08fe6dd7845a495:


package web

import (
	"regexp"
	"strings"
	"testing"
)

// THE TYPE STAYS ON THE SCALE.
//
// The stylesheet had sixty-eight distinct font sizes, most between 11
// and 14 px, written one feature at a time; next to a mockup drawn on
// seven, every page read as crowded and flat. Sizes are now tokens
// (--fs-*), or ems relative to their parent. A new raw size fails here
// rather than quietly starting the drift again.
func TestTypeStaysOnTheScale(t *testing.T) {
	sheet := paletteCSS + sheetLiteral
	raw := regexp.MustCompile(`font(?:-size)?:[^;}]*?\b\d*\.?\d+(?:rem|px)\b`)
	for _, m := range raw.FindAllString(sheet, -1) {
		if strings.Contains(m, "--fs-") && !regexp.MustCompile(`\d(?:rem|px)`).MatchString(strings.ReplaceAll(m, "var(--fs-", "")) {
			continue
		}
		t.Errorf("FAIL: %q is a raw size; use a --fs-* step or an em", m)
	}
	// Tokens themselves are declared once, in the measure block.
	if n := strings.Count(sheet, "--fs-xs:"); n != 1 {
		t.Errorf("FAIL: --fs-xs declared %d times", n)
	}
}

// Every font-family is a token (or inherits), so the face is decided in
// one place and code never falls back to the browser's monospace.
func TestFontFamiliesAreTokens(t *testing.T) {
	sheet := paletteCSS + sheetLiteral
	for _, m := range regexp.MustCompile(`font:[^;}]*\b(ui-monospace|system-ui|monospace|sans-serif|serif)\b`).FindAllString(sheet, -1) {
		if !strings.Contains(m, "var(--font-") {
			t.Errorf("FAIL: shorthand %q names a face; use var(--font-sans) or var(--font-mono)", m)
		}
	}
	for _, m := range regexp.MustCompile(`font-family:\s*([^;}]+)`).FindAllStringSubmatch(sheet, -1) {
		v := strings.TrimSpace(m[1])
		if strings.HasPrefix(v, "var(--font-") || v == "inherit" {
			continue
		}
		t.Errorf("FAIL: font-family %q; use var(--font-sans) or var(--font-mono)", v)
	}
}

// A weight with no face is synthesised or snapped by the browser, and
// differently by each; the stylesheet asks only for weights quarry
// serves a face for.
func TestWeightsHaveAFace(t *testing.T) {
	served := map[string]bool{"normal": true, "bold": true, "inherit": true}
	for _, f := range webFonts {
		served[strings.TrimSpace(strings.Fields(string(rune('0'+f.weight/100)) + "00")[0])] = true
	}
	sheet := paletteCSS + sheetLiteral
	for _, m := range regexp.MustCompile(`font-weight:\s*([0-9a-z]+)`).FindAllStringSubmatch(sheet, -1) {
		if !served[m[1]] {
			t.Errorf("FAIL: font-weight %s has no face; quarry serves 400, 500, 600 and 700", m[1])
		}
	}
	if len(webFonts) == 0 || !strings.Contains(fontFaceCSS(), "font-display:swap") {
		t.Error("FAIL: no @font-face, or one that can hold a page blank")
	}
}

// A static chip is a label, not a control. The new-ticket form's chips
// are controls with a touch height; unscoped, that height stood every
// label chip on the site 36px tall (the ticket list's type tags).
func TestOnlyTheFormsChipsAreControls(t *testing.T) {
	for _, m := range regexp.MustCompile(`(?m)^\.chip\s*\{[^}]*\}`).FindAllString(paletteCSS+sheetLiteral, -1) {
		if strings.Contains(m, "min-height") || strings.Contains(m, "cursor: pointer") {
			t.Errorf("FAIL: the site-wide .chip rule carries a control's size or cursor: %s", m)
		}
	}
}

// SPACE AND CORNERS STAY ON THEIR SCALES.
//
// The stylesheet had 187 distinct paddings and 32 radii; next to a
// mockup drawn on six gaps and two corners, the difference read as
// noise. Paddings and gaps are --sp-* steps and radii --r-* steps (a
// calc() may add them; 0, %, and em stay as they are).
func TestSpaceStaysOnTheScale(t *testing.T) {
	sheet := paletteCSS + sheetLiteral
	decl := regexp.MustCompile(`(?:^|[;{\s])((?:padding(?:-[a-z]+)?|(?:row-|column-)?gap|border(?:-[a-z]+)*-radius))\s*:([^;}]*)`)
	raw := regexp.MustCompile(`(?:^|[^\w.-])\d*\.?\d+(?:rem|px)\b`)
	for _, m := range decl.FindAllStringSubmatch(sheet, -1) {
		v := m[2]
		if strings.Contains(v, "calc(") {
			continue
		}
		if raw.MatchString(v) {
			t.Errorf("FAIL: %s:%s is off the scale; use var(--sp-*) or var(--r-*)", m[1], v)
		}
	}
}