package web
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"craftdesign.group/quarry/internal/ops"
)
// A pair with hundreds of conflicting files is a page: the first files
// get rows, the next are named by path, the rest are counted, and the
// sentence about resolving in a checkout counts every file it means.
func TestAHugeConflictIsListedNotDrawn(t *testing.T) {
var files []map[string]string
for i := 0; i < 300; i++ {
files = append(files, map[string]string{"path": fmt.Sprintf("f%03d.c", i), "kind": "text", "omitted": "past the file limit"})
}
raw, _ := json.Marshal(map[string]any{"branch": "b", "target": "trunk", "branchTip": "cap1", "targetTip": "cap2",
"verdict": "conflict", "files": files})
var rep conflictsReport
if err := json.Unmarshal(raw, &rep); err != nil {
t.Fatal(err)
}
mv := buildMeld(rep, "/r/x")
if mv.Total != 300 || len(mv.Files) != meldDrawnMax || len(mv.Rest) != meldRestMax || mv.RestMore != 300-meldDrawnMax-meldRestMax {
t.Errorf("FAIL: total=%d drawn=%d rest=%d more=%d", mv.Total, len(mv.Files), len(mv.Rest), mv.RestMore)
}
if !strings.HasPrefix(mv.Unresolvable, "300 files") || !strings.Contains(mv.Unresolvable, "f000.c") {
t.Errorf("FAIL: unresolvable reads %q", mv.Unresolvable)
}
var b bytes.Buffer
if err := noHooks.template(mergePageTmpl).ExecuteTemplate(&b, "content", pageData{Repo: "x",
Merge: &mergePage{Branch: "b", Onto: "trunk", Verdict: "conflict", Meld: mv}}); err != nil {
t.Fatal(err)
}
h := b.String()
if n := strings.Count(h, `data-hook="meld-file"`); n != meldDrawnMax || !strings.Contains(h, `data-hook="meld-rest"`) {
t.Errorf("FAIL: the page drew %d file rows", n)
}
if !strings.Contains(h, "f051.c") || strings.Contains(h, "f299.c") {
t.Error("FAIL: the named and counted files are not where they belong")
}
if !strings.Contains(h, `data-hook="meld-unresolvable"`) {
t.Error("FAIL: no word on resolving in a checkout")
}
t.Log("ok")
}
// One file past the limit is named alone; none, and nothing is said.
func TestUnresolvableNamesWhatItMeans(t *testing.T) {
one := []meldFile{{Path: "a.c"}, {Path: "big.c", Omitted: "too large"}}
if got := unresolvableOf(one); got != "big.c is too large" {
t.Errorf("FAIL: %q", got)
}
if got := unresolvableOf([]meldFile{{Path: "a.c"}}); got != "" {
t.Errorf("FAIL: %q", got)
}
t.Log("ok")
}
// The merge page with no pair to show answers with its pickers.
func TestMergePageWithNothingToPairShowsThePickers(t *testing.T) {
var b bytes.Buffer
if err := noHooks.template(mergePageTmpl).ExecuteTemplate(&b, "content", pageData{Repo: "x",
Merge: &mergePage{Onto: "trunk", Verdict: "none", Branches: []string{"trunk"}, Recent: []string{"trunk"}}}); err != nil {
t.Fatal(err)
}
h := b.String()
if !strings.Contains(h, `data-hook="merge-none"`) || !strings.Contains(h, `name="branch"`) || strings.Contains(h, `data-hook="meld"`) {
t.Errorf("FAIL: %s", h)
}
t.Log("ok")
}
// A pair the merge op cannot resolve reads as the op's sentence.
func TestAnUnresolvedPairSaysWhy(t *testing.T) {
err := fmt.Errorf("no branch or check-in %q here: %w", "main", ops.ErrNotFound)
if got := pairWhy(err); got != `No branch or check-in "main" here` {
t.Errorf("FAIL: %q", got)
}
t.Log("ok")
}