Skip to content
quarry Artifact [66c582540f]
Login

Artifact [66c582540f]

Artifact 66c582540f7148afa38d7eeae9b88e0fb116c529b22dcb25d5075757a156f147:


package web

import (
	"strings"
	"testing"
)

// The composer offers two views of one draft: Rich, reading its blocks
// from this repository's markup-blocks and its pickers' lists from
// ref.suggest, and Markdown, the textarea the form posts. There is no third Preview: Rich renders through the same
// pipeline. Without script the tab bar stays hidden and the textarea is
// the composer.
func TestTheComposerOffersRichAndMarkdown(t *testing.T) {
	var b strings.Builder
	if err := noHooks.template(forumAnnouncePage).ExecuteTemplate(&b, "content", pageData{Repo: "alpha", Composer: true}); err != nil {
		t.Fatal(err)
	}
	s := b.String()
	if !strings.Contains(s, `data-hook="composer-rich"`) || !strings.Contains(s, `data-blocks="/r/alpha/markup-blocks"`) {
		t.Error("FAIL: the composer has no Rich view reading this repository's blocks")
	}
	if !strings.Contains(s, `data-suggest="/r/alpha/ref.suggest"`) {
		t.Error("FAIL: the Rich view's pickers do not ask this repository")
	}
	if !strings.Contains(s, `data-hook="composer-write"`) || strings.Contains(s, `data-tab="preview"`) {
		t.Error("FAIL: the composer's tabs are not Rich and Markdown")
	}
	if !strings.Contains(s, `<div class="f-tabs" hidden>`) || !strings.Contains(s, `name="body"`) {
		t.Error("FAIL: without script the composer is not the plain textarea")
	}
}

// "/" opens the search everywhere except where somebody is typing, and
// the Rich composer is a place where somebody is typing: it is an
// editable element, not an input, so the shortcut has to ask.
func TestSlashSearchLeavesTheRichComposerAlone(t *testing.T) {
	shortcuts := strings.Count(baseHTML, `evt.key == '/'`)
	guarded := strings.Count(baseHTML, `evt.key == '/' &amp;&amp; !/INPUT|TEXTAREA|SELECT/.test(document.activeElement.tagName) &amp;&amp; !document.activeElement.isContentEditable`)
	if shortcuts == 0 || guarded != shortcuts {
		t.Errorf("FAIL: %d of %d search shortcuts skip an editable element", guarded, shortcuts)
	}
}

// A post's author sees Edit beside Reply, not only in the overflow
// menu, and the edit page is the composer holding the post's text.
func TestAnAuthorEditsTheirPostInTheComposer(t *testing.T) {
	data := pageData{Repo: "alpha", ForumRoot: "abc123", ForumViewer: "lou", CanWrite: true,
		ForumPosts: []forumPostRow{
			{Hash: "aaaaaaaaaaaa1111", User: "lou", HTML: "<p>mine</p>", Date: "2026-09-16T09:00:00Z"},
			{Hash: "bbbbbbbbbbbb2222", User: "mia", HTML: "<p>hers</p>", Date: "2026-09-16T09:05:00Z"},
		}}
	var b strings.Builder
	if err := noHooks.template(forumThreadPage).ExecuteTemplate(&b, "forum-posts", data); err != nil {
		t.Fatal(err)
	}
	if n := strings.Count(b.String(), `data-hook="post-edit"`); n != 1 {
		t.Errorf("FAIL: %d Edit buttons, want one, on the viewer's own post", n)
	}
	if !strings.Contains(b.String(), `/r/alpha/forum/abc123/edit/aaaaaaaaaaaa1111`) {
		t.Error("FAIL: Edit does not lead to the viewer's post")
	}
	var e strings.Builder
	edit := pageData{Repo: "alpha", ForumRoot: "abc123",
		ForumPosts: []forumPostRow{{Hash: "aaaaaaaaaaaa1111", User: "lou", Source: "the **text**"}}}
	if err := noHooks.template(forumEditPage).ExecuteTemplate(&e, "content", edit); err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(e.String(), `data-hook="composer-rich"`) || !strings.Contains(e.String(), `name="body"`) ||
		!strings.Contains(e.String(), "the **text**") {
		t.Error("FAIL: the edit page is not the composer holding the post's text")
	}
}