package codeview
import (
"strings"
"testing"
"unicode"
)
// squash is markup with every whitespace character taken out. Format
// may add, move and drop whitespace and must touch nothing else, so the
// two sides of a formatting agree once squashed. Whether the whitespace
// it moved could show is the browser's question, not this one's, and
// no drive here asks it yet (see the note above flexAttrs).
func squash(s string) string {
return strings.Map(func(r rune) rune {
if unicode.IsSpace(r) {
return -1
}
return r
}, s)
}
var formatCases = []string{
``,
`
`,
``,
}
func TestFormatChangesOnlyWhitespaceAndIsIdempotent(t *testing.T) {
for _, in := range formatCases {
out := Format(in)
if squash(out) != squash(in) {
t.Errorf("Format changed more than whitespace:\n in: %s\nout: %s", in, out)
}
if Format(out) != out {
t.Errorf("Format is not idempotent on:\n%s\nsecond pass:\n%s", out, Format(out))
}
}
}
// The space between two inline elements, and between text and an
// inline element, is rendered wherever the container is not one the
// formatter knows lays its children out as flex or grid, so Format
// keeps it exactly. An unknown container stays inline.
func TestFormatKeepsTheSpaceBetweenInlineElements(t *testing.T) {
for in, want := range map[string]string{
`
",
} {
if got := Format(in); got != want {
t.Errorf("Format(%q)\n got %q\nwant %q", in, got, want)
}
}
}
func TestFormatBreaksAtBlockTagsAndIndents(t *testing.T) {
got := Format(``)
want := "\n \n"
if got != want {
t.Errorf("got\n%s\nwant\n%s", got, want)
}
}
// Inside a flex or grid container whitespace between children renders
// as nothing, so every child gets a line: the busy button's spinner and
// its label, and the two buttons beside each other. A button holding
// only its label keeps it inline.
func TestFormatPutsEachChildOfAFlexContainerOnALine(t *testing.T) {
got := Format(formatCases[5])
want := "
"
if got != want {
t.Errorf("got\n%s\nwant\n%s", got, want)
}
got = Format(formatCases[2])
want = "\n \n 700/500\n"
if got != want {
t.Errorf("got\n%s\nwant\n%s", got, want)
}
}
// A hidden input renders nothing, so the space beside it shows only if
// something visible shares its line. At the head of a form, before the
// first thing drawn, each one gets a line.
func TestFormatPutsSilentElementsOnLinesOfTheirOwn(t *testing.T) {
got := Format(formatCases[6])
want := ""
if got != want {
t.Errorf("got\n%s\nwant\n%s", got, want)
}
// In a sentence, a hidden input between two words keeps the line it
// is on: a break there would be a space between them.
in := `
onetwo
`
if got := Format(in); got != in {
t.Errorf("a hidden input inside running text was broken out:\n%s", got)
}
}
// An element with nothing in it stays with nothing in it: :empty is a
// selector tokens.css uses, and a line break would stop it matching.
func TestFormatLeavesAnEmptyElementEmpty(t *testing.T) {
for _, in := range []string{
`
`,
``,
`
Order
`,
} {
out := Format(in)
for _, empty := range []string{``, ``, ``} {
if strings.Contains(in, empty) && !strings.Contains(out, empty) {
t.Errorf("an empty element got content:\n%s", out)
}
}
}
}
// A