package web
import (
"strings"
"testing"
)
// Editing a ticket in place rests on sibling selectors, so the toggle
// must come BEFORE everything it shows and hides. Get the order wrong
// and the pencil silently does nothing — the CSS still parses, the
// page still renders, and only a human clicking finds out.
func TestEditToggleComesBeforeWhatItControls(t *testing.T) {
for _, tc := range []struct {
toggle string
after []string
}{
{`id="t-edit-title"`, []string{`class="t-title"`, `class="t-pen"`,
`class="t-title-form"`, `class="t-cancel"`, `t-save`}},
{`id="t-edit-desc"`, []string{`t-pen-desc`, `class="tkt-body`, `t-desc-form`}},
} {
at := strings.Index(ticketSource, tc.toggle)
if at < 0 {
t.Fatalf("%s is gone; the in-place editor is not wired", tc.toggle)
}
for _, sib := range tc.after {
if i := strings.Index(ticketSource, sib); i < at {
t.Errorf("%s appears before its toggle %s, so the sibling selector "+
"never matches and the control does nothing", sib, tc.toggle)
}
}
}
}
// The checkbox is hidden by clipping, never by display:none — a control
// removed from the box tree cannot be focused, which would leave the
// editor reachable by mouse only.
func TestEditToggleStaysReachableByKeyboard(t *testing.T) {
if !strings.Contains(ticketSource, `class="t-toggle sr-only"`) {
t.Error("the edit toggle is not sr-only; check it is still focusable")
}
if strings.Contains(styleSource, ".t-toggle { display: none") {
t.Error("the edit toggle is display:none, so keyboard users cannot reach it")
}
// Cancel and the pencil drive the same checkbox, which is what makes
// cancelling cost no round trip.
if strings.Count(ticketSource, `for="t-edit-title"`) < 2 {
t.Error("Cancel does not share the title toggle; cancelling would need a reload")
}
}
// The pencil sits at the body's bottom-right corner, in room the body
// reserves for it, so no line of text can ever run beneath it.
func TestDescriptionPencilHasReservedRoom(t *testing.T) {
tk := tktFixture()
tk.Description = "a body"
html := renderTkt(t, "content", pageData{Repo: "q", Ticket: tk, CanWrite: true,
DescriptionHTML: "<p>a body</p>"})
if !strings.Contains(html, `t-pen-desc`) {
t.Fatalf("the description pencil is gone:\n%s", html)
}
if !strings.Contains(html, `class="tkt-body tkt-body-pen"`) {
t.Errorf("the editable body does not carry the reserving class")
}
ro := renderTkt(t, "content", pageData{Repo: "q", Ticket: tk, DescriptionHTML: "<p>a body</p>"})
if strings.Contains(ro, `tkt-body-pen`) {
t.Errorf("a read-only body reserves room for a pencil it does not draw")
}
if !strings.Contains(sheet, ".t-pen-desc { position: absolute; bottom: 0; right: 0;") ||
!strings.Contains(sheet, ".tkt-body-pen { padding-bottom:") {
t.Errorf("the stylesheet neither anchors the pencil bottom-right nor reserves its room")
}
}