Download
77 lines 2.6 KiBGoModified 2026-10-31 raw
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
package tools

import (
	"strings"
	"testing"

	"blinker/internal/htmlmd"
)

func TestFetchURL(t *testing.T) {
	u, frag, err := fetchURL("https://docs.python.org/3/library/stdtypes.html#lists")
	if err != nil || u != "https://docs.python.org/3/library/stdtypes.html" || frag != "lists" {
		t.Errorf("fetchURL = %q, %q, %v", u, frag, err)
	}
	for _, bad := range []string{
		"http://docs.python.org/",
		"file:///etc/passwd",
		"https:///path",
		"https://user:pw@docs.python.org/",
		"https://docs.python.org/a b",
		"https://docs.python.org/a\nb",
		"https://docs.python.org/\u202e",
		"-K/etc/passwd",
		"https:docs.python.org",
	} {
		if _, _, err := fetchURL(bad); err == nil {
			t.Errorf("fetchURL(%q) accepted", bad)
		}
	}
}

func TestFetchName(t *testing.T) {
	a := fetchName("https://docs.python.org/3/library/stdtypes.html", "md")
	if !strings.HasPrefix(a, "docs.python.org-3-library-stdtypes.html-") || !strings.HasSuffix(a, ".md") {
		t.Errorf("fetchName = %q", a)
	}
	// URLs that read alike once cut get different names, and none climbs
	// out of the directory.
	b := fetchName("https://docs.python.org/3/library/stdtypes.html?x", "md")
	c := fetchName("https://x/../../../etc/passwd", "md")
	if a == b || strings.Contains(c, "/") || strings.HasPrefix(c, ".") {
		t.Errorf("fetchName: %q, %q, %q", a, b, c)
	}
}

func TestConvertPage(t *testing.T) {
	out, kind, conv, err := convertPage([]byte(`<!doctype html><h1 id="top">Top</h1><p>Text.</p>`))
	if err != nil || kind != "md" || conv == nil || string(out) != "# Top\n\nText.\n" || conv.Anchors["top"] != 1 {
		t.Errorf("HTML: %q, %q, %+v, %v", out, kind, conv, err)
	}
	out, kind, _, err = convertPage([]byte(`{"a":[1,2]}`))
	if err != nil || kind != "json" || string(out) != "{\n  \"a\": [\n    1,\n    2\n  ]\n}\n" {
		t.Errorf("JSON: %q, %q, %v", out, kind, err)
	}
	out, kind, _, err = convertPage([]byte("plain\x1b[2J text\xff"))
	if err != nil || kind != "txt" || string(out) != "plain[2J text�\n" {
		t.Errorf("text: %q, %q, %v", out, kind, err)
	}
	if _, _, _, err := convertPage([]byte("\x89PNG\r\n\x1a\n\x00\x00")); err == nil || !strings.Contains(err.Error(), "image/png") {
		t.Errorf("image: %v", err)
	}
}

func TestOutline(t *testing.T) {
	if outline(nil) != "" {
		t.Error("an outline of no headings")
	}
	var hs []htmlmd.Heading
	for i := range 200 {
		hs = append(hs, htmlmd.Heading{Line: i + 1, Level: 2 + i%2, Text: "h"})
	}
	// 200 headings do not fit; the 100 at level 2 do.
	got := outline(hs)
	if strings.Count(got, "\n") != 1+100+1 || strings.Contains(got, "### h") || !strings.Contains(got, "(100 more headings") {
		t.Errorf("outline:\n%s", got)
	}
}