package web
import (
"strings"
"testing"
)
// TestRenderDocDiffUnchanged proves a proposal that does not change a document
// is reported as unchanged rather than as an empty diff.
func TestRenderDocDiffUnchanged(t *testing.T) {
src := []byte("# Title\n\nOne paragraph.\n")
v := renderDocDiff(src, src)
if !v.Unchanged {
t.Fatalf("Unchanged = false, want true for identical input")
}
if v.HTML != "" {
t.Errorf("HTML = %q, want empty for an unchanged document", v.HTML)
}
}
// TestRenderDocDiffInlineWordChange proves a small edit renders inline with
// <del>/<ins> marks and not as two columns.
func TestRenderDocDiffInlineWordChange(t *testing.T) {
old := []byte("# Title\n\nThe quick brown fox jumps over the lazy dog.\n")
nw := []byte("# Title\n\nThe quick red fox jumps over the lazy dog.\n")
v := renderDocDiff(old, nw)
if v.Unchanged {
t.Fatalf("Unchanged = true, want a change")
}
html := string(v.HTML)
if !strings.Contains(html, "<del>brown</del>") {
t.Errorf("missing inline deletion of 'brown'; got:\n%s", html)
}
if !strings.Contains(html, "<ins>red</ins>") {
t.Errorf("missing inline insertion of 'red'; got:\n%s", html)
}
if strings.Contains(html, "ph-columns") {
t.Errorf("a one-word edit rendered as two columns; got:\n%s", html)
}
}
// TestRenderDocDiffTwoColumnBelowThreshold proves a block rewritten enough to
// fall below the similarity threshold renders as the two-column old/new view —
// the Phase 0 verdict's hard requirement.
func TestRenderDocDiffTwoColumnBelowThreshold(t *testing.T) {
// A block rewritten to ~0.58 similarity: paired as a modify (above the 0.40
// pairing floor) but shredded enough to fall below the 0.75 inline switch.
old := []byte("# Title\n\nThe committee approved the annual budget after a long and " +
"contentious debate that lasted well into the evening.\n")
nw := []byte("# Title\n\nThe committee rejected the annual budget after a brief and " +
"quiet discussion that ended early in the afternoon.\n")
v := renderDocDiff(old, nw)
html := string(v.HTML)
if !strings.Contains(html, "ph-columns") {
t.Fatalf("a wholesale rewrite did not render as two columns; got:\n%s", html)
}
if !strings.Contains(html, "ph-col ph-old") || !strings.Contains(html, "ph-col ph-new") {
t.Errorf("two-column view missing an old or new column; got:\n%s", html)
}
}
// TestRenderDocDiffEscapesContent proves document content is HTML-escaped: a
// document that contains markup cannot inject it into the review page.
func TestRenderDocDiffEscapesContent(t *testing.T) {
old := []byte("# Title\n\nplain text here.\n")
nw := []byte("# Title\n\nplain <script>alert(1)</script> text here.\n")
v := renderDocDiff(old, nw)
html := string(v.HTML)
if strings.Contains(html, "<script>") {
t.Fatalf("unescaped <script> reached the output; got:\n%s", html)
}
if !strings.Contains(html, "<script>") {
t.Errorf("expected the escaped script tag in the output; got:\n%s", html)
}
}
// TestRenderDocDiffInsertAndDelete proves an added and a removed block are each
// shown whole, labelled.
func TestRenderDocDiffInsertAndDelete(t *testing.T) {
old := []byte("# Title\n\nKept paragraph.\n\nDoomed paragraph.\n")
nw := []byte("# Title\n\nKept paragraph.\n\nBrand new paragraph.\n")
v := renderDocDiff(old, nw)
html := string(v.HTML)
if !strings.Contains(html, "ph-insert") {
t.Errorf("missing an inserted block; got:\n%s", html)
}
if !strings.Contains(html, "ph-delete") {
t.Errorf("missing a deleted block; got:\n%s", html)
}
}